]> git.eshelyaron.com Git - emacs.git/commitdiff
New user option 'completion-preview-idle-delay'
authorEshel Yaron <me@eshelyaron.com>
Wed, 5 Jun 2024 08:23:56 +0000 (10:23 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 5 Jun 2024 10:15:52 +0000 (12:15 +0200)
Support displaying the completion preview shortly after you
pause typing (on idle) rather than immediately.

* lisp/completion-preview.el (Commentary): Update.
(completion-preview--try-update):
(completion-preview--update-from-timer): New functions.
(completion-preview--timer): New buffer-local variable.
(completion-preview-idle-delay): New user option.
(completion-preview--show): Use it.
(completion-preview--post-command):
(completion-preview-mode): Disable idle timer if active.

(cherry picked from commit f240f482e2686f9c51d33b9e11b5884b12cef7aa)

lisp/completion-preview.el

index 64aba08ebbd6e8ab31ca352091688f816b3c28e1..57badf4726d415ab5031b7e158efcfd6eae414d2 100644 (file)
 ;; that should appear around point for Emacs to suggest a completion.
 ;; By default, this option is set to 3, so Emacs suggests a completion
 ;; if you type "foo", but typing just "fo" doesn't show the preview.
+;; If you want the preview to appear also after non-symbol characters,
+;; such as punctuation, set `completion-preview-minimum-symbol-length'
+;; to nil.  If you do so, you may want to customize the user option
+;; `completion-preview-idle-delay' to have the preview appear only
+;; when you pause typing for a short duration rather than after every
+;; key.  Try setting it to 0.2 seconds and see how that works for you.
 
 ;;; Code:
 
@@ -124,6 +130,14 @@ If this option is nil, these commands do not display any message."
                  (const :tag "No message" nil))
   :version "30.1")
 
+(defcustom completion-preview-idle-delay nil
+  "If non-nil, wait this many idle seconds before displaying completion preview.
+
+If this is nil, display the completion preview without delay."
+  :type '(choice (number :tag "Delay duration in seconds")
+                 (const :tag "No delay" nil))
+  :version "30.1")
+
 (defvar completion-preview-sort-function #'minibuffer--sort-by-length-alpha
   "Sort function to use for choosing a completion candidate to preview.")
 
@@ -407,6 +421,18 @@ candidates or if there are multiple matching completions and
         (overlay-put ov 'completion-preview-props props)
         (completion-preview-active-mode)))))
 
+(defun completion-preview--try-update ()
+  "Try to update completion preview, but give up as soon as input arrives."
+  (while-no-input (completion-preview--update)))
+
+(defun completion-preview--update-from-timer (window buffer)
+  "Update completion preview if WINDOW and BUFFER are current."
+  (when (and (eq (selected-window) window) (eq (current-buffer) buffer))
+    (completion-preview--try-update)))
+
+(defvar-local completion-preview--timer nil
+  "Idle timer for updating the completion preview.")
+
 (defun completion-preview--show ()
   "Show a new completion preview.
 
@@ -459,7 +485,12 @@ point, otherwise hide it."
         ;; The previous preview is no longer applicable, hide it.
         (completion-preview-active-mode -1))))
   ;; Run `completion-at-point-functions' to get a new candidate.
-  (while-no-input (completion-preview--update)))
+  (if completion-preview-idle-delay
+      (setq completion-preview--timer
+            (run-with-idle-timer completion-preview-idle-delay
+                                 nil #'completion-preview--update-from-timer
+                                 (selected-window) (current-buffer)))
+    (completion-preview--try-update)))
 
 (defun completion-preview--post-command ()
   "Create, update or delete completion preview post last command."
@@ -468,6 +499,10 @@ point, otherwise hide it."
                               completion-preview--internal-commands))))
     (setq completion-preview--inhibit-update-p nil)
 
+    (when (timerp completion-preview--timer)
+      (cancel-timer completion-preview--timer)
+      (setq completion-preview--timer nil))
+
     ;; If we're called after a command that itself updates the
     ;; preview, don't do anything.
     (unless internal-p
@@ -637,7 +672,10 @@ backward."
   (if completion-preview-mode
       (add-hook 'post-command-hook #'completion-preview--post-command 10 t)
     (remove-hook 'post-command-hook #'completion-preview--post-command t)
-    (completion-preview-active-mode -1)))
+    (when completion-preview-active-mode (completion-preview-active-mode -1))
+    (when (timerp completion-preview--timer)
+      (cancel-timer completion-preview--timer)
+      (setq completion-preview--timer nil))))
 
 ;;;###autoload
 (define-globalized-minor-mode global-completion-preview-mode