From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Jules Tamagnan Newsgroups: gmane.emacs.bugs Subject: bug#71716: [PATCH] Add new completion-preview-insert-{word, sexp} commands Date: Sat, 22 Jun 2024 02:11:18 -0700 Message-ID: <87a5jd8hqh.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="23713"; mail-complaints-to="usenet@ciao.gmane.io" To: 71716@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Jun 22 11:12:52 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sKwnj-0005yK-V2 for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 22 Jun 2024 11:12:52 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sKwn7-0002RV-5m; Sat, 22 Jun 2024 05:12:14 -0400 Original-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 ) id 1sKwn0-0002Qn-2M for bug-gnu-emacs@gnu.org; Sat, 22 Jun 2024 05:12:06 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sKwmx-0004fj-Cz for bug-gnu-emacs@gnu.org; Sat, 22 Jun 2024 05:12:04 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1sKwmx-0000uh-1r for bug-gnu-emacs@gnu.org; Sat, 22 Jun 2024 05:12:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Jules Tamagnan Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 22 Jun 2024 09:12:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 71716 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.17190475063461 (code B ref -1); Sat, 22 Jun 2024 09:12:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 22 Jun 2024 09:11:46 +0000 Original-Received: from localhost ([127.0.0.1]:44414 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sKwme-0000tj-PB for submit@debbugs.gnu.org; Sat, 22 Jun 2024 05:11:45 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:43704) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sKwmY-0000tD-Dv for submit@debbugs.gnu.org; Sat, 22 Jun 2024 05:11:41 -0400 Original-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 ) id 1sKwmW-0002OL-Q2 for bug-gnu-emacs@gnu.org; Sat, 22 Jun 2024 05:11:38 -0400 Original-Received: from mail-pl1-x630.google.com ([2607:f8b0:4864:20::630]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sKwmS-0004VP-T6 for bug-gnu-emacs@gnu.org; Sat, 22 Jun 2024 05:11:35 -0400 Original-Received: by mail-pl1-x630.google.com with SMTP id d9443c01a7336-1fa07e4f44eso4699665ad.2 for ; Sat, 22 Jun 2024 02:11:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1719047491; x=1719652291; darn=gnu.org; h=mime-version:message-id:date:subject:to:from:from:to:cc:subject :date:message-id:reply-to; bh=wMW4pGZYvGpxeSfX1Ny8i/lIyXnLsU2uCdaDoQiaLlM=; b=VKZ7kQEfpDCycRWfF8UKoL2w62pZnSySpvEm1X/BIZf8HLpa7qDCEDQe6zsmtWchBz bhXtckYIzZEQyvu3A/Rmb+vR84pCl6WzwHi0iVLcx4IIRiWzsm+KiVxof6bmtHzO0s3B PajPp2va7Nll+0iNwrUCU515+W3xVP5kOkXmPsPmzQyq5/YKI8S/8pt8AIE6AOC+JZQG bA9wBq90eoscDxMvTcpH53cf+LJjVwJRfeA8tzM6TD6Bfm6AGre7TdfHAxT7G68rjI1m SmwxFrh2yhkbEhZU3seMggK319DnYQDr5s/PgOpEnMZmv9L9CTP1a9UOey+n+A9Y60o0 wJmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719047491; x=1719652291; h=mime-version:message-id:date:subject:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=wMW4pGZYvGpxeSfX1Ny8i/lIyXnLsU2uCdaDoQiaLlM=; b=NyCyGsCCeDIefGy7m7ZqIKk3kUUAx8KS+vWVUavbjt9Lzs3ig2OhiZFO2an86zX9e8 V/ln2JqzWfsJ2v9t0cNZveCyybG9kfeuQr5cmw8LbG4Mnjw+SKGMF516feq/BDJ0lFeD 4yJPUtzWnbys9Ljwg86Nr1jwelHahglaBKMoraS5q6Mq8YCJbd8hBsUbnx3JEiAexN3p d+Vx5qCgpht8tzisXRtUPVH4e82EqP+lI9m2fwODmIJj/5wzA0A+qDXT461JLK3ODICk YSN+3On1lOFSJNuHIzlhkIPQCtV0CCOswr9/KjtPh+HdoDkHiw9jOvEEpZblQZV57F5Y kdqg== X-Gm-Message-State: AOJu0YybOiJ+bTWweRfSvIkDt14jqwR54sMDp+dMbESX8ENP+9BDThCI rIPGd4ofYigxACF1yWr4AUPA1hBnCJ3JzgE6b0M7nNqyGHynsCGSG6HuuQ== X-Google-Smtp-Source: AGHT+IFSNd4x15L4OCbyE8bBlhpPfNxJ+EWwfJAlq7XJbOZXrCVPBIupm463i0jNlUP3EReeenpdpw== X-Received: by 2002:a17:903:41cb:b0:1fa:1750:132c with SMTP id d9443c01a7336-1fa1750152fmr3788505ad.5.1719047490385; Sat, 22 Jun 2024 02:11:30 -0700 (PDT) Original-Received: from jat-framework (syn-024-043-218-043.biz.spectrum.com. [24.43.218.43]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1f9eb3219b1sm27015015ad.94.2024.06.22.02.11.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jun 2024 02:11:29 -0700 (PDT) Received-SPF: pass client-ip=2607:f8b0:4864:20::630; envelope-from=jtamagnan@gmail.com; helo=mail-pl1-x630.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-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:287678 Archived-At: --=-=-= Content-Type: text/plain Tags: patch * Problem Oftentimes when completing a value a user wants a small part of a completion but not the entire thing. This happens frequently when iterating on shell commands or on similar lines of code. completion-preview can help with this by quickly suggesting a sensible completion pulled from any completion-at-point function. The problem is that accepting a full completion is often inefficient because one might only want the first part of that completion. This leads to a lot of deletions after the fact. * Solution Allow inserting of partial completions when using completion-preview. For this I've added two new commands completion-preview-insert-word and completion-preview-insert-sexp which will insert the next word or sexp in the completion. For consistency with completion-preview-insert I've refactored the code so that these three commands share a common code path. * Notes - I've added new tests for this and ensured that previous ones continue to pass. - I've signed the copyright assignments and have contributed to emacs previously. * Info In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.42, cairo version 1.18.0) Repository revision: 988203fe980e3c80f736ad0b6aae9f288ebfa0f1 Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12101013 System Description: NixOS 24.11 (Vicuna) Configured using: 'configure --prefix=/nix/store/3riplzxicrgaff4jm49wa4vvvrd6yd1l-emacs-git-20240615.0 --disable-build-details --with-modules --with-x-toolkit=gtk3 --with-cairo --with-xft --with-compress-install --with-toolkit-scroll-bars --with-native-compilation --without-imagemagick --with-mailutils --without-small-ja-dic --with-tree-sitter --with-xinput2 --with-xwidgets --with-dbus --with-selinux' --=-=-= Content-Type: text/patch Content-Disposition: attachment; filename=0001-Add-new-completion-preview-insert-word-sexp-commands.patch >From d78a9a4209d050dcb2a410610d70840d35b9b722 Mon Sep 17 00:00:00 2001 From: Jules Tamagnan Date: Sat, 22 Jun 2024 00:45:01 -0700 Subject: [PATCH] Add new completion-preview-insert-{word,sexp} commands * lisp/completion-preview.el: Add new completion-preview-insert-word and completion-preview-insert-sexp commands. * test/lisp/completion-preview-tests.el: Add tests for new commands. --- lisp/completion-preview.el | 56 +++++++++++++++++++-------- test/lisp/completion-preview-tests.el | 52 +++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el index caebb9d01e3..3a7fa37afe0 100644 --- a/lisp/completion-preview.el +++ b/lisp/completion-preview.el @@ -90,7 +90,9 @@ completion-preview-commands delete-backward-char backward-delete-char-untabify analyze-text-conversion - completion-preview-complete) + completion-preview-complete + completion-preview-insert-word + completion-preview-insert-sexp) "List of commands that should trigger completion preview." :type '(repeat (function :tag "Command" :value self-insert-command)) :version "30.1") @@ -163,6 +165,8 @@ completion-preview-active-mode-map "M-i" #'completion-preview-complete ;; "M-n" #'completion-preview-next-candidate ;; "M-p" #'completion-preview-prev-candidate + ;; " " #'completion-preview-insert-word + ;; " " #'completion-preview-insert-sexp ) (defun completion-preview--ignore () @@ -444,24 +448,42 @@ completion-preview--post-command (completion-preview--show) (completion-preview-active-mode -1))))) +(defun completion-preview--insert (action) + "A helper function to insert part of the completion candidate that the +preview is showing." + (if completion-preview-active-mode + (let* ((beg (completion-preview--get 'completion-preview-beg)) + (end (completion-preview--get 'completion-preview-end)) + (efn (plist-get (completion-preview--get 'completion-preview-props) + :exit-function)) + (ful (completion-preview--get 'after-string)) + (aft (with-temp-buffer + (insert ful) + (goto-char (point-min)) + (funcall action) + (buffer-substring-no-properties (point-min) (point))))) + (completion-preview-active-mode -1) + (goto-char end) + (insert aft) + (when (and (functionp efn) (string= ful aft)) + ;; If we've inserted a full completion call the exit-function + (funcall efn (concat (buffer-substring-no-properties beg end) aft) 'finished))) + (user-error "No current completion preview"))) + (defun completion-preview-insert () "Insert the completion candidate that the preview is showing." (interactive) - (if completion-preview-active-mode - (let* ((pre (completion-preview--get 'completion-preview-base)) - (end (completion-preview--get 'completion-preview-end)) - (ind (completion-preview--get 'completion-preview-index)) - (all (completion-preview--get 'completion-preview-suffixes)) - (com (completion-preview--get 'completion-preview-common)) - (efn (plist-get (completion-preview--get 'completion-preview-props) - :exit-function)) - (aft (completion-preview--get 'after-string)) - (str (concat pre com (nth ind all)))) - (completion-preview-active-mode -1) - (goto-char end) - (insert (substring-no-properties aft)) - (when (functionp efn) (funcall efn str 'finished))) - (user-error "No current completion preview"))) + (completion-preview--insert #'end-of-buffer)) + +(defun completion-preview-insert-word () + "Insert the next word of the completion candidate that the preview is showing." + (interactive) + (completion-preview--insert #'forward-word)) + +(defun completion-preview-insert-sexp () + "Insert the next sexp of the completion candidate that the preview is showing." + (interactive) + (completion-preview--insert #'forward-sexp)) (defun completion-preview-complete () "Complete up to the longest common prefix of all completion candidates. @@ -583,6 +605,8 @@ completion-preview--active-p (buffer-local-value 'completion-preview-active-mode buffer)) (dolist (cmd '(completion-preview-insert + completion-preview-insert-word + completion-preview-insert-sexp completion-preview-complete completion-preview-prev-candidate completion-preview-next-candidate)) diff --git a/test/lisp/completion-preview-tests.el b/test/lisp/completion-preview-tests.el index 7d358d07519..dedd135da73 100644 --- a/test/lisp/completion-preview-tests.el +++ b/test/lisp/completion-preview-tests.el @@ -292,7 +292,7 @@ completion-preview-insert-calls-exit-function (setq-local completion-at-point-functions (list (completion-preview-tests--capf - '("foobar" "foobaz") + '("foobar-1 2" "foobarverylong") :exit-function (lambda (&rest args) (setq exit-fn-called t @@ -300,11 +300,55 @@ completion-preview-insert-calls-exit-function (insert "foo") (let ((this-command 'self-insert-command)) (completion-preview--post-command)) - (completion-preview-tests--check-preview "bar" 'completion-preview-common) + (completion-preview-tests--check-preview "bar-1 2" 'completion-preview-common) (completion-preview-insert) - (should (string= (buffer-string) "foobar")) + (should (string= (buffer-string) "foobar-1 2")) (should-not completion-preview--overlay) (should exit-fn-called) - (should (equal exit-fn-args '("foobar" finished)))))) + (should (equal exit-fn-args '("foobar-1 2" finished)))))) + +(ert-deftest completion-preview-insert-word () + "Test that `completion-preview-insert-word' properly inserts just a word." + (let ((exit-fn-called nil) (exit-fn-args nil)) + (with-temp-buffer + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foobar-1 2" "foobarverylong") + :exit-function + (lambda (&rest args) + (setq exit-fn-called t + exit-fn-args args))))) + (insert "foo") + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "bar-1 2" 'completion-preview-common) + (completion-preview-insert-word) + (should (string= (buffer-string) "foobar")) + (should-not completion-preview--overlay) + (should-not exit-fn-called) + (should-not exit-fn-args)))) + +(ert-deftest completion-preview-insert-sexp () + "Test that `completion-preview-insert-word' properly inserts just a sexp." + (let ((exit-fn-called nil) (exit-fn-args nil)) + (with-temp-buffer + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foobar-1 2" "foobarverylong") + :exit-function + (lambda (&rest args) + (setq exit-fn-called t + exit-fn-args args))))) + (insert "foo") + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "bar-1 2" 'completion-preview-common) + (completion-preview-insert-sexp) + (should (string= (buffer-string) "foobar-1")) + (should-not completion-preview--overlay) + (should-not exit-fn-called) + (should-not exit-fn-args)))) ;;; completion-preview-tests.el ends here -- 2.45.1 --=-=-=--