emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/aggressive-completion 4a6065a: Add new package aggressi


From: Tassilo Horn
Subject: [elpa] externals/aggressive-completion 4a6065a: Add new package aggressive-completion.el
Date: Sat, 3 Apr 2021 13:36:22 -0400 (EDT)

branch: externals/aggressive-completion
commit 4a6065a29b190b43894112a0bac0f08af2bb2f32
Author: Tassilo Horn <tsdh@gnu.org>
Commit: Tassilo Horn <tsdh@gnu.org>

    Add new package aggressive-completion.el
---
 aggressive-completion.el | 181 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 181 insertions(+)

diff --git a/aggressive-completion.el b/aggressive-completion.el
new file mode 100644
index 0000000..d0f593a
--- /dev/null
+++ b/aggressive-completion.el
@@ -0,0 +1,181 @@
+;;; aggressive-completion.el --- Automatic minibuffer completion -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Tassilo Horn <tsdh@gnu.org>
+;; Maintainer: Tassilo Horn <tsdh@gnu.org>
+;; Keywords: minibuffer completion
+;; Package-Requires: ((emacs "27.1"))
+;; Version: 1.0
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Aggressive completion mode (`aggressive-completion-mode') is a minor mode
+;; which automatically completes for you after a short delay
+;; (`aggressive-completion-delay') and always shows all possible completions
+;; using the standard completion help (unless the number of possible
+;; completions exceeds `aggressive-completion-max-shown-completions').
+;;
+;; Automatic completion is temporarily disabled after all commands in
+;; `aggressive-completion-no-complete-commands'.  Basically all deletion/kill
+;; commands are listed here in order not to complete back to the thing you just
+;; deleted.
+;;
+;; Aggressive completion can be toggled using
+;; `aggressive-completion-toggle-auto-complete' (bound to `M-t' by default)
+;; which is especially useful when trying to find a not yet existing file or
+;; switch to a new buffer.
+;;
+;; You can switch from minibuffer to *Completions* buffer and back again using
+;; `aggressive-completion-switch-to-completions' (bound to `M-c' by default).
+;; All keys bound to this command in `aggressive-completion-minibuffer-map'
+;; will be bound to `other-window' in `completion-list-mode-map' so that those
+;; keys act as switch-back-and-forth commands.
+
+;;; Code:
+
+(eval-when-compile
+  ;; For `when-let'.
+  (require 'subr-x))
+
+(defgroup aggressive-completion nil
+  "Aggressive completion completes for you."
+  :group 'completion)
+
+(defcustom aggressive-completion-delay 0.3
+  "Delay in seconds before aggressive completion kicks in."
+  :type 'number)
+
+(defcustom aggressive-completion-auto-complete t
+  "Complete automatically if non-nil.
+If nil, only show the completion help."
+  :type 'boolean)
+
+(defcustom aggressive-completion-max-shown-completions 1000
+  "Maximum number of possible completions for showing completion help."
+  :type 'integer)
+
+(defcustom aggressive-completion-no-complete-commands
+  '( left-char icomplete-fido-backward-updir minibuffer-complete
+     right-char delete-backward-char backward-kill-word
+     backward-kill-paragraph backward-kill-sentence backward-kill-sexp
+     delete-char kill-word kill-line completion-at-point)
+  "Commands after which automatic completion is not performed."
+  :type '(repeat command))
+
+(defvar aggressive-completion--timer nil)
+
+(defun aggressive-completion--do ()
+  "Perform aggressive completion."
+  (when (window-minibuffer-p)
+    (let* ((completions (completion-all-sorted-completions))
+           ;; Don't ding if there are no completions, etc.
+           (visible-bell nil)
+           (ring-bell-function #'ignore)
+           ;; Automatic completion should not cycle.
+           (completion-cycle-threshold nil)
+           (completion-cycling nil))
+      (let ((i 0))
+        (while (and (<= i aggressive-completion-max-shown-completions)
+                    (consp completions))
+          (setq completions (cdr completions))
+          (cl-incf i))
+        (if (and (> i 0)
+                 (< i aggressive-completion-max-shown-completions))
+            (if (or (null aggressive-completion-auto-complete)
+                    (memq last-command
+                          aggressive-completion-no-complete-commands))
+                ;; This ensures we still can repeatedly hit TAB to scroll
+                ;; through the list of completions.
+                (unless (and (= last-command-event ?\t)
+                             (window-live-p
+                              (get-buffer-window "*Completions*"))
+                             (with-current-buffer "*Completions*"
+                               (> (point) (point-min))))
+                  (minibuffer-completion-help))
+              (minibuffer-complete)
+              (unless (window-live-p (get-buffer-window "*Completions*"))
+                (minibuffer-completion-help)))
+          ;; Close the *Completions* buffer if there are too many
+          ;; or zero completions.
+          (when-let ((win (get-buffer-window "*Completions*")))
+            (when (and (window-live-p win)
+                       (not (memq last-command
+                                  '(minibuffer-completion-help
+                                    minibuffer-complete
+                                    completion-at-point))))
+              (quit-window nil win))))))))
+
+(defun aggressive-completion--timer-restart ()
+  "Restart `aggressive-completion--timer'."
+  (when aggressive-completion--timer
+    (cancel-timer aggressive-completion--timer))
+
+  (setq aggressive-completion--timer
+        (run-with-idle-timer aggressive-completion-delay nil
+                             #'aggressive-completion--do)))
+
+(defun aggressive-completion-toggle-auto-complete ()
+  "Toggle automatic completion."
+  (interactive)
+  (setq aggressive-completion-auto-complete
+        (not aggressive-completion-auto-complete)))
+
+;; Add an alias so that we can find out the bound key using
+;; `where-is-internal'.
+(defalias 'aggressive-completion-switch-to-completions
+  #'switch-to-completions)
+
+(defvar aggressive-completion-minibuffer-map
+  (let ((map (make-sparse-keymap)))
+    (require 'icomplete)
+    (define-key map (kbd "DEL") #'icomplete-fido-backward-updir)
+    (define-key map (kbd "M-t") #'aggressive-completion-toggle-auto-complete)
+    (define-key map (kbd "M-c") #'aggressive-completion-switch-to-completions)
+    map)
+  "The local minibuffer keymap when `aggressive-completion-mode' is enabled.")
+
+(defun aggressive-completion--setup ()
+  "Setup aggressive completion."
+  (when (and (not executing-kbd-macro)
+             (window-minibuffer-p)
+             minibuffer-completion-table)
+    (set-keymap-parent aggressive-completion-minibuffer-map 
(current-local-map))
+    (use-local-map aggressive-completion-minibuffer-map)
+
+    ;; If `aggressive-completion-switch-to-completions' is bound to keys, bind
+    ;; the same keys in `completion-list-mode-map' to `other-window' so that
+    ;; one can conveniently switch back and forth using the same key.
+    (dolist (key (where-is-internal
+                 #'aggressive-completion-switch-to-completions))
+      (define-key completion-list-mode-map key #'other-window))
+
+    (add-hook 'post-command-hook
+              #'aggressive-completion--timer-restart nil t)))
+
+(define-minor-mode aggressive-completion-mode
+  "Perform aggressive minibuffer completion."
+  :lighter " ACmp"
+  :global t
+  (if aggressive-completion-mode
+      (add-hook 'minibuffer-setup-hook #'aggressive-completion--setup)
+    (remove-hook 'minibuffer-setup-hook #'aggressive-completion--setup)))
+
+(provide 'aggressive-completion)
+
+;;; aggressive-completion.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]