From 5761e9004aa73d3aa7c34be9a064a1e768c3129c Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Sat, 10 Apr 2021 11:47:45 +0100 Subject: Add new icomplete-vertical-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Távora * lisp/icomplete.el (icomplete-completions): Consider icomplete-vertical-mode. (icomplete-vertical-mode-minibuffer-map): New map. (icomplete--vertical-minibuffer-setup): New helper. (icomplete-vertical-mode): New minor mode. * doc/emacs/buffers.texi (Icomplete): Mention icomplete-vertical-mode. * etc/NEWS: Mention icomplete-vertical-mode --- lisp/icomplete.el | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index da589c00649..d5b6f76d7b2 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -562,6 +562,37 @@ Usually run by inclusion in `minibuffer-setup-hook'." (completion--cache-all-sorted-completions beg end (cons comp all)))) finally return all))) +(defvar icomplete-vertical-mode-minibuffer-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-n") 'icomplete-forward-completions) + (define-key map (kbd "C-p") 'icomplete-backward-completions) + map) + "Keymap used by `icomplete-vertical-mode' in the minibuffer.") + +(defun icomplete--vertical-minibuffer-setup () + "Setup the minibuffer for vertical display of completion candidates." + (use-local-map (make-composed-keymap icomplete-vertical-mode-minibuffer-map + (current-local-map))) + (setq-local icomplete-separator "\n" + icomplete-hide-common-prefix nil + ;; Ask `icomplete-completions' to return enough completions candidates. + icomplete-prospects-height 25 + redisplay-adhoc-scroll-in-resize-mini-windows nil)) + +;;;###autoload +(define-minor-mode icomplete-vertical-mode + "Toggle vertical candidate display in `icomplete-mode' or `fido-mode'. + +As many completion candidates as possible are displayed, depending on +the value of `max-mini-window-height', and the way the mini-window is +resized depends on `resize-mini-windows'." + :global t + (remove-hook 'icomplete-minibuffer-setup-hook + #'icomplete--vertical-minibuffer-setup) + (when icomplete-vertical-mode + (add-hook 'icomplete-minibuffer-setup-hook + #'icomplete--vertical-minibuffer-setup))) + @@ -784,10 +815,13 @@ matches exist." (if last (setcdr last base-size)) (if prospects (concat determ - "{" - (mapconcat 'identity prospects icomplete-separator) - (and limit (concat icomplete-separator ellipsis)) - "}") + (if icomplete-vertical-mode " \n" "{") + (mapconcat 'identity prospects (if icomplete-vertical-mode + "\n" + icomplete-separator)) + (unless icomplete-vertical-mode + (concat (and limit (concat icomplete-separator ellipsis)) + "}"))) (concat determ " [Matched]")))))) ;;; Iswitchb compatibility -- cgit v1.2.3 From 289ec2d911c0a723c0c131ac9cf3407c71a4b15c Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 16 Apr 2021 14:28:10 +0200 Subject: ; Remove some useless comments --- lisp/align.el | 2 -- lisp/allout-widgets.el | 1 - lisp/allout.el | 1 - lisp/autorevert.el | 1 - lisp/bs.el | 1 - lisp/cus-edit.el | 2 -- lisp/cus-face.el | 2 -- lisp/custom.el | 2 -- lisp/emacs-lisp/faceup.el | 5 ----- lisp/emacs-lisp/lisp-mnt.el | 5 ----- lisp/emacs-lisp/ring.el | 2 -- lisp/expand.el | 1 - lisp/filecache.el | 4 ---- lisp/filenotify.el | 1 - lisp/gnus/gnus-cus.el | 2 -- lisp/gnus/gnus-diary.el | 5 ----- lisp/gnus/gnus-registry.el | 2 -- lisp/gnus/nnselect.el | 1 - lisp/icomplete.el | 1 - lisp/language/thai-word.el | 2 +- lisp/mh-e/mh-acros.el | 2 -- lisp/mh-e/mh-alias.el | 2 -- lisp/mh-e/mh-buffers.el | 2 -- lisp/mh-e/mh-comp.el | 2 -- lisp/mh-e/mh-compat.el | 2 -- lisp/mh-e/mh-folder.el | 2 -- lisp/mh-e/mh-funcs.el | 2 -- lisp/mh-e/mh-gnus.el | 2 -- lisp/mh-e/mh-identity.el | 2 -- lisp/mh-e/mh-inc.el | 2 -- lisp/mh-e/mh-junk.el | 2 -- lisp/mh-e/mh-letter.el | 2 -- lisp/mh-e/mh-limit.el | 2 -- lisp/mh-e/mh-mime.el | 2 -- lisp/mh-e/mh-print.el | 2 -- lisp/mh-e/mh-scan.el | 2 -- lisp/mh-e/mh-search.el | 2 -- lisp/mh-e/mh-seq.el | 2 -- lisp/mh-e/mh-show.el | 2 -- lisp/mh-e/mh-speed.el | 2 -- lisp/mh-e/mh-thread.el | 2 -- lisp/mh-e/mh-tool-bar.el | 2 -- lisp/mh-e/mh-utils.el | 2 -- lisp/mh-e/mh-xface.el | 2 -- lisp/net/ange-ftp.el | 4 ---- lisp/obsolete/fast-lock.el | 2 -- lisp/obsolete/lazy-lock.el | 2 -- lisp/obsolete/nnir.el | 1 - lisp/obsolete/sregex.el | 4 +--- lisp/progmodes/glasses.el | 4 ---- lisp/progmodes/meta-mode.el | 3 --- lisp/progmodes/python.el | 2 -- lisp/speedbar.el | 1 - lisp/textmodes/bibtex-style.el | 1 - lisp/textmodes/bibtex.el | 3 --- lisp/textmodes/makeinfo.el | 1 - lisp/textmodes/page.el | 2 -- lisp/textmodes/tex-mode.el | 1 - lisp/textmodes/texinfmt.el | 6 ++---- lisp/textmodes/texnfo-upd.el | 2 -- lisp/textmodes/tildify.el | 2 -- lisp/uniquify.el | 2 -- lisp/vc/vc-hg.el | 4 ---- lisp/widget.el | 2 -- test/manual/cedet/tests/test.el | 3 --- 65 files changed, 4 insertions(+), 139 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/align.el b/lisp/align.el index 7ae067f8c53..a0b626a5c43 100644 --- a/lisp/align.el +++ b/lisp/align.el @@ -1587,8 +1587,6 @@ aligner would have dealt with are." (if report (message "Aligning...done")))) -;; Provide: - (provide 'align) (run-hooks 'align-load-hook) diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el index 931dfbc961e..90f3f61b363 100644 --- a/lisp/allout-widgets.el +++ b/lisp/allout-widgets.el @@ -2290,7 +2290,6 @@ The elements of LIST are not copied, just the list structure itself." (define-obsolete-function-alias 'allout-frame-property #'frame-parameter "28.1") -;;;_ : provide (provide 'allout-widgets) ;;;_ . Local emacs vars. diff --git a/lisp/allout.el b/lisp/allout.el index f50f5fd4b2c..1605ce2ce33 100644 --- a/lisp/allout.el +++ b/lisp/allout.el @@ -6457,7 +6457,6 @@ If BEG is bigger than END we return 0." (isearch-repeat 'forward) (isearch-mode t))) -;;;_ #11 Provide (provide 'allout) ;;;_* Local emacs vars. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 1bb40c90ff5..edd4c7e5e45 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -937,7 +937,6 @@ the timer when no buffers need to be checked." (cancel-timer auto-revert-timer)) (setq auto-revert-timer nil))))) -;; The end: (provide 'autorevert) (run-hooks 'auto-revert-load-hook) diff --git a/lisp/bs.el b/lisp/bs.el index 154e3599f33..494bc426188 100644 --- a/lisp/bs.el +++ b/lisp/bs.el @@ -1504,7 +1504,6 @@ name of buffer configuration." ;; continue standard unloading nil) -;; Now provide feature bs (provide 'bs) ;;; bs.el ends here diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index dde6e8997bf..7627930c4c8 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -5155,8 +5155,6 @@ if that value is non-nil." (put 'Custom-mode 'mode-class 'special) -;;; The End. - (provide 'cus-edit) ;;; cus-edit.el ends here diff --git a/lisp/cus-face.el b/lisp/cus-face.el index 21fe89c6214..6c0052bf860 100644 --- a/lisp/cus-face.el +++ b/lisp/cus-face.el @@ -395,8 +395,6 @@ This means reset FACE to its value in FROM-THEME." (define-obsolete-function-alias 'custom-facep #'facep "28.1") -;;; The End. - (provide 'cus-face) ;;; cus-face.el ends here diff --git a/lisp/custom.el b/lisp/custom.el index 85e5d65ffb2..2c9eadbd479 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -1623,8 +1623,6 @@ If a choice with the same tag already exists, no action is taken." (put variable 'custom-type (append choices (list choice)))))) -;;; The End. - (provide 'custom) ;;; custom.el ends here diff --git a/lisp/emacs-lisp/faceup.el b/lisp/emacs-lisp/faceup.el index 6c3931f9829..162c39634ed 100644 --- a/lisp/emacs-lisp/faceup.el +++ b/lisp/emacs-lisp/faceup.el @@ -1170,11 +1170,6 @@ Intended to be called when a file is loaded." ;; File is being evaluated using, for example, `eval-buffer'. default-directory))) - -;; ---------------------------------------------------------------------- -;; The end -;; - (provide 'faceup) ;;; faceup.el ends here diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el index 6d9c8c32794..73a33a553fb 100644 --- a/lisp/emacs-lisp/lisp-mnt.el +++ b/lisp/emacs-lisp/lisp-mnt.el @@ -109,11 +109,6 @@ ;; * Footer line --- marks end-of-file so it can be distinguished from ;; an expanded formfeed or the results of truncation. -;;; Change Log: - -;; Tue Jul 14 23:44:17 1992 ESR -;; * Created. - ;;; Code: ;;; Variables: diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el index 96894655b45..ea27bb3c31b 100644 --- a/lisp/emacs-lisp/ring.el +++ b/lisp/emacs-lisp/ring.el @@ -248,8 +248,6 @@ If SEQ is already a ring, return it." (ring-insert-at-beginning ring (elt seq count)))) ring))) -;;; provide ourself: - (provide 'ring) ;;; ring.el ends here diff --git a/lisp/expand.el b/lisp/expand.el index d11ae7c5263..1b722014f89 100644 --- a/lisp/expand.el +++ b/lisp/expand.el @@ -484,7 +484,6 @@ This is used only in conjunction with `expand-add-abbrevs'." (provide 'expand) -;; run load hooks (run-hooks 'expand-load-hook) ;;; expand.el ends here diff --git a/lisp/filecache.el b/lisp/filecache.el index 67d2939dd3c..62184e1a0ae 100644 --- a/lisp/filecache.el +++ b/lisp/filecache.el @@ -674,10 +674,6 @@ match REGEXP." (insert (nth 1 item) (nth 0 item) "\n")) (pop-to-buffer buf)))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Keybindings -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (provide 'filecache) ;;; filecache.el ends here diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 07871bb0b64..4fc7f0a8ec0 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -505,7 +505,6 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." ;; due to the way events are propagated during idle time. Note: This ;; may be perfectly acceptable. -;; The end: (provide 'filenotify) ;;; filenotify.el ends here diff --git a/lisp/gnus/gnus-cus.el b/lisp/gnus/gnus-cus.el index 0852f8e1264..e7af94ff509 100644 --- a/lisp/gnus/gnus-cus.el +++ b/lisp/gnus/gnus-cus.el @@ -1102,8 +1102,6 @@ articles in the thread. (widget-setup) (buffer-enable-undo)))) -;;; The End: - (provide 'gnus-cus) ;;; gnus-cus.el ends here diff --git a/lisp/gnus/gnus-diary.el b/lisp/gnus/gnus-diary.el index 64eb639f61c..e2cbca9007d 100644 --- a/lisp/gnus/gnus-diary.el +++ b/lisp/gnus/gnus-diary.el @@ -32,11 +32,6 @@ ;; gnus-diary is a utility toolkit used on top of the nndiary back end. It is ;; now fully documented in the Gnus manual. - -;; Bugs / Todo: -;; =========== - - ;;; Code: (require 'nndiary) diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el index 6ac646fbeac..11b6f7ddf07 100644 --- a/lisp/gnus/gnus-registry.el +++ b/lisp/gnus/gnus-registry.el @@ -1298,8 +1298,6 @@ from your existing entries." (gnus-registry-insert db k newv))) (registry-reindex db)))) -;; TODO: a few things - (provide 'gnus-registry) ;;; gnus-registry.el ends here diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el index e314e1d8d10..5ac4c3a64e1 100644 --- a/lisp/gnus/nnselect.el +++ b/lisp/gnus/nnselect.el @@ -968,7 +968,6 @@ Pass NO-PARSE on to the search engine." (gnus-group-make-search-group no-parse spec))) -;; The end. (provide 'nnselect) ;;; nnselect.el ends here diff --git a/lisp/icomplete.el b/lisp/icomplete.el index d5b6f76d7b2..91bbb600136 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -837,7 +837,6 @@ matches exist." ;;;###autoload (make-obsolete 'iswitchb-mode ;;;###autoload "use `icomplete-mode' or `ido-mode' instead." "24.4")) -;;;_* Provide (provide 'icomplete) ;;_* Local emacs vars. diff --git a/lisp/language/thai-word.el b/lisp/language/thai-word.el index ff1e80298ba..7a09bc3a24a 100644 --- a/lisp/language/thai-word.el +++ b/lisp/language/thai-word.el @@ -11074,4 +11074,4 @@ With argument, do this that many times." ;; coding: utf-8 ;; End: -;; end of thai-word.el +;; thai-word.el ends here diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el index dd953ee9df7..8fdcf3c62b4 100644 --- a/lisp/mh-e/mh-acros.el +++ b/lisp/mh-e/mh-acros.el @@ -36,8 +36,6 @@ ;; because it's pointless to compile a file full of macros. But we ;; kept the name. -;;; Change Log: - ;;; Code: (require 'cl-lib) diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el index 67c019aa179..415e9848258 100644 --- a/lisp/mh-e/mh-alias.el +++ b/lisp/mh-e/mh-alias.el @@ -24,8 +24,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-buffers.el b/lisp/mh-e/mh-buffers.el index a32f61c82eb..ef21fdb2f95 100644 --- a/lisp/mh-e/mh-buffers.el +++ b/lisp/mh-e/mh-buffers.el @@ -24,8 +24,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: ;; The names of ephemeral buffers have a " *mh-" prefix (so that they diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el index c1cd6c1a9e2..b64bbfb6f3b 100644 --- a/lisp/mh-e/mh-comp.el +++ b/lisp/mh-e/mh-comp.el @@ -29,8 +29,6 @@ ;; that are used to send the mail. Other that those, functions that ;; are needed in mh-letter.el should be found there. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-compat.el b/lisp/mh-e/mh-compat.el index 0363c5aadac..ade80e8b95e 100644 --- a/lisp/mh-e/mh-compat.el +++ b/lisp/mh-e/mh-compat.el @@ -23,8 +23,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: ;; This is a good place to gather code that is used for compatibility diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el index 2e288064f16..ce77f9c0971 100644 --- a/lisp/mh-e/mh-folder.el +++ b/lisp/mh-e/mh-folder.el @@ -25,8 +25,6 @@ ;; Mode for browsing folders -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el index 38ba43188da..0e5ffc9a42c 100644 --- a/lisp/mh-e/mh-funcs.el +++ b/lisp/mh-e/mh-funcs.el @@ -30,8 +30,6 @@ ;; small support routines are needed, place them with the function; ;; otherwise, create a separate section for them. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el index ac46cc63fcc..cc60f7b6640 100644 --- a/lisp/mh-e/mh-gnus.el +++ b/lisp/mh-e/mh-gnus.el @@ -24,8 +24,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el index aeab0497562..ceede0d07cb 100644 --- a/lisp/mh-e/mh-identity.el +++ b/lisp/mh-e/mh-identity.el @@ -33,8 +33,6 @@ ;; in MH-Letter mode. The command `mh-insert-identity' can be used ;; to manually insert an identity. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el index 6a29195afbb..83cfe4f99f1 100644 --- a/lisp/mh-e/mh-inc.el +++ b/lisp/mh-e/mh-inc.el @@ -28,8 +28,6 @@ ;; inc can also be used to incorporate mail from multiple spool files ;; into separate folders. See "C-h v mh-inc-spool-list". -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el index 5a407947a0b..e50bf8df50c 100644 --- a/lisp/mh-e/mh-junk.el +++ b/lisp/mh-e/mh-junk.el @@ -26,8 +26,6 @@ ;; Spam handling in MH-E. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-letter.el b/lisp/mh-e/mh-letter.el index 59790181c4d..ae5b80d5807 100644 --- a/lisp/mh-e/mh-letter.el +++ b/lisp/mh-e/mh-letter.el @@ -31,8 +31,6 @@ ;; mh-utils.el. That will help prevent the loading of this file until ;; a message is actually composed. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el index 08f1b4093f1..39cf7c5d271 100644 --- a/lisp/mh-e/mh-limit.el +++ b/lisp/mh-e/mh-limit.el @@ -25,8 +25,6 @@ ;; "Poor man's threading" by psg. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el index fec2293ff1f..ef702525b7b 100644 --- a/lisp/mh-e/mh-mime.el +++ b/lisp/mh-e/mh-mime.el @@ -36,8 +36,6 @@ ;; MIME option to mh-forward command to move to content-description ;; insertion point. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-print.el b/lisp/mh-e/mh-print.el index d084cf63e97..2074ff6f8f3 100644 --- a/lisp/mh-e/mh-print.el +++ b/lisp/mh-e/mh-print.el @@ -24,8 +24,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el index f00ab22958a..15049793adf 100644 --- a/lisp/mh-e/mh-scan.el +++ b/lisp/mh-e/mh-scan.el @@ -27,8 +27,6 @@ ;; This file contains constants and a few functions for interpreting ;; scan lines. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el index cb8f8e34558..9df7c326564 100644 --- a/lisp/mh-e/mh-search.el +++ b/lisp/mh-e/mh-search.el @@ -39,8 +39,6 @@ ;; documentation will direct you to the specific instructions for ;; your particular searcher. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el index 9b9675c78e1..9cdf39f7f1e 100644 --- a/lisp/mh-e/mh-seq.el +++ b/lisp/mh-e/mh-seq.el @@ -26,8 +26,6 @@ ;; Sequences are stored in the alist `mh-seq-list' in the form: ;; ((seq-name msgs ...) (seq-name msgs ...) ...) -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el index cb9819f17c7..6134e8350c8 100644 --- a/lisp/mh-e/mh-show.el +++ b/lisp/mh-e/mh-show.el @@ -26,8 +26,6 @@ ;; Mode for showing messages. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el index b2deacf6a74..3af840c3a31 100644 --- a/lisp/mh-e/mh-speed.el +++ b/lisp/mh-e/mh-speed.el @@ -26,8 +26,6 @@ ;; Future versions should only use flists. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el index 01b6863038b..89b0dbd9798 100644 --- a/lisp/mh-e/mh-thread.el +++ b/lisp/mh-e/mh-thread.el @@ -69,8 +69,6 @@ ;; (5) Better canonicalizing for message identifier and subject ;; strings. -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-tool-bar.el b/lisp/mh-e/mh-tool-bar.el index 40a430b9641..94aa8dd4a92 100644 --- a/lisp/mh-e/mh-tool-bar.el +++ b/lisp/mh-e/mh-tool-bar.el @@ -24,8 +24,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el index e73c1db9e45..8e900dc0113 100644 --- a/lisp/mh-e/mh-utils.el +++ b/lisp/mh-e/mh-utils.el @@ -24,8 +24,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el index 0b53829b056..d4d5c5c3784 100644 --- a/lisp/mh-e/mh-xface.el +++ b/lisp/mh-e/mh-xface.el @@ -23,8 +23,6 @@ ;;; Commentary: -;;; Change Log: - ;;; Code: (require 'mh-e) diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index 86b5d449872..04ea8091277 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -6258,10 +6258,6 @@ be recognized automatically (they are all valid BS2000 hosts too)." ;; ange-ftp-bs2000-file-name-as-directory ;; ange-ftp-bs2000-make-compressed-filename ;; ange-ftp-bs2000-file-name-sans-versions - -;;;; ------------------------------------------------------------ -;;;; Finally provide package. -;;;; ------------------------------------------------------------ (provide 'ange-ftp) diff --git a/lisp/obsolete/fast-lock.el b/lisp/obsolete/fast-lock.el index baed8be7663..960233d5627 100644 --- a/lisp/obsolete/fast-lock.el +++ b/lisp/obsolete/fast-lock.el @@ -752,8 +752,6 @@ See `fast-lock-get-face-properties'." (unless (assq 'fast-lock-mode minor-mode-alist) (setq minor-mode-alist (append minor-mode-alist '((fast-lock-mode nil))))) -;; Provide ourselves: - (provide 'fast-lock) ;;; fast-lock.el ends here diff --git a/lisp/obsolete/lazy-lock.el b/lisp/obsolete/lazy-lock.el index 34bf85f864c..13f14aad6d1 100644 --- a/lisp/obsolete/lazy-lock.el +++ b/lisp/obsolete/lazy-lock.el @@ -1016,8 +1016,6 @@ verbosity is controlled via the variable `lazy-lock-stealth-verbose'." (unless (assq 'lazy-lock-mode minor-mode-alist) (setq minor-mode-alist (append minor-mode-alist '((lazy-lock-mode nil))))) -;; Provide ourselves: - (provide 'lazy-lock) ;; Local Variables: diff --git a/lisp/obsolete/nnir.el b/lisp/obsolete/nnir.el index f2ea5c67ceb..40a8ec57b98 100644 --- a/lisp/obsolete/nnir.el +++ b/lisp/obsolete/nnir.el @@ -1339,7 +1339,6 @@ Query for the specs, or use SPECS." (define-obsolete-function-alias 'nnir-get-active #'gnus-server-get-active "28.1") -;; The end. (provide 'nnir) ;;; nnir.el ends here diff --git a/lisp/obsolete/sregex.el b/lisp/obsolete/sregex.el index 96d6b7aebf0..371dcbf8498 100644 --- a/lisp/obsolete/sregex.el +++ b/lisp/obsolete/sregex.el @@ -208,7 +208,7 @@ ;; This is a "trapdoor" for including ordinary regular expression ;; strings in the result. Some regular expressions are clearer when ;; written the old way: "[a-z]" vs. (sregexq (char (?a . ?z))), for -;; instance. However, see the note under "Bugs," below. +;; instance. ;; Each CHAR-CLAUSE that is passed to (char ...) and (not-char ...) ;; has one of the following forms: @@ -236,8 +236,6 @@ ;; - add support for non-greedy operators *? and +? ;; - bug: (sregexq (opt (opt ?a))) returns "a??" which is a non-greedy "a?" -;;; Bugs: - ;;; Code: (eval-when-compile (require 'cl-lib)) diff --git a/lisp/progmodes/glasses.el b/lisp/progmodes/glasses.el index a0f5d36bb65..cd92175bd61 100644 --- a/lisp/progmodes/glasses.el +++ b/lisp/progmodes/glasses.el @@ -321,10 +321,6 @@ separators (like underscores) at places they belong to." (remove-hook 'write-file-functions 'glasses-convert-to-unreadable t))))) - -;;; Announce - (provide 'glasses) - ;;; glasses.el ends here diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el index a59014827e8..50268446025 100644 --- a/lisp/progmodes/meta-mode.el +++ b/lisp/progmodes/meta-mode.el @@ -942,9 +942,6 @@ The environment marked is the one that contains point or follows point." (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list) (list "" 'ispell-complete-word)))) - -;;; Just in case ... - (provide 'meta-mode) (run-hooks 'meta-mode-load-hook) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 30721c7a577..20ec339fffb 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -247,8 +247,6 @@ ;; I'd recommend the first one since you'll get the same behavior for ;; all modes out-of-the-box. -;;; TODO: - ;;; Code: (require 'ansi-color) diff --git a/lisp/speedbar.el b/lisp/speedbar.el index 12e57b11082..118c7260769 100644 --- a/lisp/speedbar.el +++ b/lisp/speedbar.el @@ -4055,7 +4055,6 @@ this version is not backward compatible to 0.14 or earlier.") (provide 'speedbar) -;; run load-time hooks (run-hooks 'speedbar-load-hook) ;;; speedbar ends here diff --git a/lisp/textmodes/bibtex-style.el b/lisp/textmodes/bibtex-style.el index 6d01871bc52..27b2e0e3331 100644 --- a/lisp/textmodes/bibtex-style.el +++ b/lisp/textmodes/bibtex-style.el @@ -24,7 +24,6 @@ ;; Done: font-lock, imenu, outline, commenting, indentation. ;; Todo: tab-completion. -;; Bugs: ;;; Code: diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index f01c66b1584..31186fb4fac 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el @@ -5608,8 +5608,5 @@ If APPEND is non-nil, append ENTRIES to those already displayed." (setq buffer-read-only t) (goto-char (point-min))) - -;; Make BibTeX a Feature - (provide 'bibtex) ;;; bibtex.el ends here diff --git a/lisp/textmodes/makeinfo.el b/lisp/textmodes/makeinfo.el index 8152f4b89c8..653540ad415 100644 --- a/lisp/textmodes/makeinfo.el +++ b/lisp/textmodes/makeinfo.el @@ -284,7 +284,6 @@ line LINE of the window, or centered if LINE is nil." (pop-to-buffer old-buffer) ))) -;;; Place `provide' at end of file. (provide 'makeinfo) ;;; makeinfo.el ends here diff --git a/lisp/textmodes/page.el b/lisp/textmodes/page.el index e1d7fb7431c..b86a2f149de 100644 --- a/lisp/textmodes/page.el +++ b/lisp/textmodes/page.el @@ -170,8 +170,6 @@ point, respectively." (interactive) (apply #'message (cons "Page %d, line %d" (page--what-page)))) - -;;; Place `provide' at end of file. (provide 'page) ;;; page.el ends here diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el index fb57b9b0f23..8d7f459190b 100644 --- a/lisp/textmodes/tex-mode.el +++ b/lisp/textmodes/tex-mode.el @@ -28,7 +28,6 @@ ;;; Code: -;; Pacify the byte-compiler (eval-when-compile (require 'compare-w) (require 'cl-lib) diff --git a/lisp/textmodes/texinfmt.el b/lisp/textmodes/texinfmt.el index a797df9193f..5ce39da7968 100644 --- a/lisp/textmodes/texinfmt.el +++ b/lisp/textmodes/texinfmt.el @@ -23,10 +23,10 @@ ;;; Commentary: -;;; Code: - ;;; Emacs lisp functions to convert Texinfo files to Info files. +;;; Code: + (defvar texinfmt-version "2.42 of 7 Jul 2006") (make-obsolete-variable 'texinfmt-version 'emacs-version "28.1") @@ -4310,8 +4310,6 @@ For example, invoke (setq error 1)))) (kill-emacs error)))) - -;;; Place `provide' at end of file. (provide 'texinfmt) ;;; texinfmt.el ends here diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el index 27807a95e60..03004548302 100644 --- a/lisp/textmodes/texnfo-upd.el +++ b/lisp/textmodes/texnfo-upd.el @@ -2112,8 +2112,6 @@ chapter." (message "Multiple files updated.")) - -;; Place `provide' at end of file. (provide 'texnfo-upd) ;;; texnfo-upd.el ends here diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el index 163978b4315..01e2ad72d88 100644 --- a/lisp/textmodes/tildify.el +++ b/lisp/textmodes/tildify.el @@ -503,8 +503,6 @@ variable will be set to the representation." (remove-hook 'post-self-insert-hook #'tildify-space t))) -;;; *** Announce *** - (provide 'tildify) ;;; tildify.el ends here diff --git a/lisp/uniquify.el b/lisp/uniquify.el index 1d513d60376..7cc01687f49 100644 --- a/lisp/uniquify.el +++ b/lisp/uniquify.el @@ -498,8 +498,6 @@ For use on `kill-buffer-hook'." (file-name-directory filename) retval))) retval)) -;;; The End - (defun uniquify-unload-function () "Unload the uniquify library." (save-current-buffer diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index a054a7c3176..c9c1e91d483 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -26,10 +26,6 @@ ;; This is a mercurial version control backend -;;; Thanks: - -;;; Bugs: - ;;; Todo: ;; 1) Implement the rest of the vc interface. See the comment at the diff --git a/lisp/widget.el b/lisp/widget.el index 401b4cf298f..d258e6fae2b 100644 --- a/lisp/widget.el +++ b/lisp/widget.el @@ -94,8 +94,6 @@ The third argument DOC is a documentation string for the widget." ;; This is used by external widget code (in W3, at least). (define-obsolete-function-alias 'widget-plist-member #'plist-member "26.1") -;;; The End. - (provide 'widget) ;;; widget.el ends here diff --git a/test/manual/cedet/tests/test.el b/test/manual/cedet/tests/test.el index a54c253be68..d1d0d1602f4 100644 --- a/test/manual/cedet/tests/test.el +++ b/test/manual/cedet/tests/test.el @@ -153,7 +153,4 @@ (defvar-mode-local emacs-lisp-mode a-mode-local-def "some value") - -;;; Provide -;; (provide 'test) -- cgit v1.2.3 From 05ab6e53e2cc82edb0b0916c880bdaa269267528 Mon Sep 17 00:00:00 2001 From: João Távora Date: Sun, 30 May 2021 16:26:02 +0100 Subject: Improve icomplete-vertical-mode and fido-vertical-mode This mode is intended to be used with Icomplete ('M-x icomplete-mode') or Fido ('M-x fido-mode'), to display the list of completions candidates vertically instead of horizontally. When used with Icomplete, completions are rotated and selection kept at the top. When used with Fido, completions scroll like a typical dropdown widget. If the dropdown behaviour is desired for Icomplete (instead of rotation), icomplete-scroll can be adjusted separately by the user. * etc/NEWS (icomplete-vertical-mode): Reword. * lisp/icomplete.el (simple): Require it. (icomplete-selected-match): New face. (icomplete-scroll): New user-visible var. (icomplete-forward-completions): Rework. (icomplete-backward-completions): Rework. (icomplete--fido-mode-setup): Prefer icomplete-scroll according to icomplete-vertical mode. (icomplete-minibuffer-setup): Initialize icomplete--scrolled-completions. (fido-vertical-mode): An alias for icomplete-vertical-mode. (icomplete-exhibit): Init icomplete--scrolled-past. Adjust overlay. (icomplete--render-vertical): New helper. (icomplete--sorted-completions): If cache is stale, also invalidate icomplete--scrolled-past. (icomplete-completions): Rework. Mostly reformat. * lisp/simple.el (max-mini-window-lines): New helper. (display-message-or-buffer): Use it. --- etc/NEWS | 10 +- lisp/icomplete.el | 362 +++++++++++++++++++++++++++++++++++------------------- lisp/simple.el | 21 ++-- 3 files changed, 257 insertions(+), 136 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/etc/NEWS b/etc/NEWS index fe8789c60b3..914e6890321 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -534,9 +534,13 @@ indentation is done using SMIE or with the old ad-hoc code. ** Icomplete +++ -*** New minor mode 'icomplete-vertical-mode'. -This mode is intended to be used with Icomplete or Fido, to display the -list of completions candidates vertically instead of horizontally. +*** New minor mode 'icomplete-vertical-mode', alias 'fido-vertical-mode' +This mode is intended to be used with Icomplete ('M-x icomplete-mode') +or Fido ('M-x fido-mode'), to display the list of completions +candidates vertically instead of horizontally. When used with +Icomplete, completions are rotated and selection kept at the top. +When used with Fido, completions scroll like a typical dropdown +widget. --- ** Specific warnings can now be disabled from the warning buffer. diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 91bbb600136..f813a1776e8 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -50,6 +50,8 @@ ;;; Code: (require 'rfn-eshadow) ; rfn-eshadow-overlay +(require 'simple) ; max-mini-window-lines +(require 'cl-lib) (defgroup icomplete nil "Show completions dynamically in minibuffer." @@ -99,6 +101,10 @@ Otherwise this should be a list of the completion tables (e.g., "Face used by Icomplete for highlighting first match." :version "24.4") +(defface icomplete-selected-match '((t :inherit highlight)) + "Face used by `icomplete-vertical-mode' for the selected candidate." + :version "24.4") + ;;;_* User Customization variables (defcustom icomplete-prospects-height 2 ;; We used to compute how many lines 100 characters would take in @@ -215,6 +221,29 @@ the default otherwise." ;; We're not at all interested in cycling here (bug#34077). (minibuffer-force-complete nil nil 'dont-cycle)) +;; Apropos `icomplete-scroll', we implement "scrolling icomplete" +;; within classic icomplete, which is "rotating", by contrast. +;; +;; The two variables supporing this are +;; `icomplete--scrolled-completions' and `icomplete--scrolled-past'. +;; They come into play when: +;; +;; - The user invokes commands `icomplete-forward-completions' and +;; `icomplete-backward-completions', thus "manually" scrolling to a +;; given position; +;; +;; - The user re-filters a selection that had already been manually +;; scrolled. The system attempts to keep the previous selection +;; stable in the face of the new filtering. This is mostly done in +;; `icomplete--render-vertical'. +;; +(defvar icomplete-scroll nil + "If non-nil, scroll candidates list instead of rotating it.") +(defvar icomplete--scrolled-completions nil + "If non-nil, tail of completions list manually scrolled to.") +(defvar icomplete--scrolled-past nil + "If non-nil, reverse tail of completions scrolled past.") + (defun icomplete-forward-completions () "Step forward completions by one entry. Second entry becomes the first and can be selected with @@ -223,10 +252,14 @@ Second entry becomes the first and can be selected with (let* ((beg (icomplete--field-beg)) (end (icomplete--field-end)) (comps (completion-all-sorted-completions beg end)) - (last (last comps))) - (when comps - (setcdr last (cons (car comps) (cdr last))) - (completion--cache-all-sorted-completions beg end (cdr comps))))) + (last (last comps))) + (when (consp (cdr comps)) + (cond (icomplete-scroll + (push (pop comps) icomplete--scrolled-past) + (setq icomplete--scrolled-completions comps)) + (t + (setcdr (last comps) (cons (pop comps) (cdr last))))) + (completion--cache-all-sorted-completions beg end comps)))) (defun icomplete-backward-completions () "Step backward completions by one entry. @@ -236,12 +269,16 @@ Last entry becomes the first and can be selected with (let* ((beg (icomplete--field-beg)) (end (icomplete--field-end)) (comps (completion-all-sorted-completions beg end)) - (last-but-one (last comps 2)) - (last (cdr last-but-one))) - (when (consp last) ; At least two elements in comps - (setcdr last-but-one (cdr last)) - (push (car last) comps) - (completion--cache-all-sorted-completions beg end comps)))) + last-but-one) + (cond ((and icomplete-scroll icomplete--scrolled-past) + (push (pop icomplete--scrolled-past) comps) + (setq icomplete--scrolled-completions comps)) + ((and (not icomplete-scroll) + (consp (cdr (setq last-but-one (last comps 2))))) + ;; At least two elements in comps + (push (car (cdr last-but-one)) comps) + (setcdr last-but-one (cdr (cdr last-but-one))))) + (completion--cache-all-sorted-completions beg end comps))) ;;; Helpers for `fido-mode' (or `ido-mode' emulation) ;;; @@ -351,6 +388,7 @@ if that doesn't produce a completion match." (setq-local icomplete-tidy-shadowed-file-names t icomplete-show-matches-on-no-input t icomplete-hide-common-prefix nil + icomplete-scroll (not (null icomplete-vertical-mode)) completion-styles '(flex) completion-flex-nospace nil completion-category-defaults nil @@ -449,6 +487,7 @@ Usually run by inclusion in `minibuffer-setup-hook'." (when (and icomplete-mode (icomplete-simple-completing-p)) (setq-local icomplete--initial-input (icomplete--field-string)) (setq-local completion-show-inline-help nil) + (setq icomplete--scrolled-completions nil) (use-local-map (make-composed-keymap icomplete-minibuffer-map (current-local-map))) (add-hook 'pre-command-hook #'icomplete-pre-command-hook nil t) @@ -483,6 +522,7 @@ Usually run by inclusion in `minibuffer-setup-hook'." (defun icomplete--sorted-completions () (or completion-all-sorted-completions (cl-loop + initially (setq icomplete--scrolled-past nil) ; Invalidate scrolled state with beg = (icomplete--field-beg) with end = (icomplete--field-end) with all = (completion-all-sorted-completions beg end) @@ -593,6 +633,8 @@ resized depends on `resize-mini-windows'." (add-hook 'icomplete-minibuffer-setup-hook #'icomplete--vertical-minibuffer-setup))) +(defalias 'fido-vertical-mode 'icomplete-vertical-mode) + @@ -659,13 +701,85 @@ See `icomplete-mode' and `minibuffer-setup-hook'." deactivate-mark) ;; Do nothing if while-no-input was aborted. (when (stringp text) - (move-overlay icomplete-overlay (point) (point) (current-buffer)) + (move-overlay icomplete-overlay (point-min) (point) (current-buffer)) ;; The current C cursor code doesn't know to use the overlay's ;; marker's stickiness to figure out whether to place the cursor ;; before or after the string, so let's spoon-feed it the pos. (put-text-property 0 1 'cursor t text) + (overlay-put + icomplete-overlay 'before-string + (and icomplete-scroll + (let ((past (length icomplete--scrolled-past))) + (format + "%s/%s " + (1+ past) + (+ past + (safe-length completion-all-sorted-completions)))))) (overlay-put icomplete-overlay 'after-string text)))))))) +(cl-defun icomplete--render-vertical (comps &aux scroll-above scroll-below) + ;; Welcome to loopapalooza! + ;; + ;; First, be mindful of `icomplete-scroll' and manual scrolls. If + ;; `icomplete--scrolled-completions' and `icomplete--scrolled-past' + ;; are: + ;; + ;; - both nil, there is no manual scroll; + ;; - both non-nil, there is a healthy manual scroll the doesn't need + ;; to be readjusted (user just moved around the minibuffer, for + ;; example)l + ;; - non-nil and nil, respectively, a refiltering took place and we + ;; need attempt to readjust them to the new filtered `comps'. + (when (and icomplete-scroll + icomplete--scrolled-completions + (null icomplete--scrolled-past)) + (cl-loop with preds + for (comp . rest) on comps + when (equal comp (car icomplete--scrolled-completions)) + do + (setq icomplete--scrolled-past preds + comps (cons comp rest)) + (completion--cache-all-sorted-completions + (icomplete--field-beg) + (icomplete--field-end) + comps) + and return nil + do (push comp preds) + finally (setq icomplete--scrolled-completions nil))) + ;; Then, in this pretty ugly loop, collect completions to display + ;; above and below the selected one, considering scrolling + ;; positions. + (cl-loop with preds = icomplete--scrolled-past + with succs = (cdr comps) + with max-lines = (1- (min + icomplete-prospects-height + (truncate (max-mini-window-lines) 1))) + with max-above = (- max-lines + 1 + (cl-loop for (_ . r) on comps + repeat (truncate max-lines 2) + while (listp r) + count 1)) + repeat max-lines + for neighbour = nil + if (and preds (> max-above 0)) do + (push (setq neighbour (pop preds)) scroll-above) + (cl-decf max-above) + else if (consp succs) collect + (setq neighbour (pop succs)) into scroll-below-aux + while neighbour + finally (setq scroll-below scroll-below-aux)) + ;; Now figure out spacing and layout + ;; + (let ((selected (substring (car comps)))) + (add-face-text-property 0 (length selected) + 'icomplete-selected-match 'append selected) + (concat " " icomplete-separator + (mapconcat + #'identity + (nconc scroll-above (list selected) scroll-below) + icomplete-separator)))) + ;;;_ > icomplete-completions (name candidates predicate require-match) (defun icomplete-completions (name candidates predicate require-match) "Identify prospective candidates for minibuffer completion. @@ -703,126 +817,126 @@ matches exist." predicate)) (md (completion--field-metadata (icomplete--field-beg))) (comps (icomplete--sorted-completions)) - (last (if (consp comps) (last comps))) - (base-size (cdr last)) (open-bracket (if require-match "(" "[")) (close-bracket (if require-match ")" "]"))) ;; `concat'/`mapconcat' is the slow part. (if (not (consp comps)) (progn ;;(debug (format "Candidates=%S field=%S" candidates name)) (format " %sNo matches%s" open-bracket close-bracket)) - (if last (setcdr last nil)) - (let* ((most-try - (if (and base-size (> base-size 0)) + (if icomplete-vertical-mode + (icomplete--render-vertical comps) + (let* ((last (if (consp comps) (last comps))) + ;; Save the "base size" encoded in `comps' then + ;; removing making `comps' a proper list. + (base-size (prog1 (cdr last) + (if last (setcdr last nil)))) + (most-try + (if (and base-size (> base-size 0)) + (completion-try-completion + name candidates predicate (length name) md) + ;; If the `comps' are 0-based, the result should be + ;; the same with `comps'. (completion-try-completion - name candidates predicate (length name) md) - ;; If the `comps' are 0-based, the result should be - ;; the same with `comps'. - (completion-try-completion - name comps nil (length name) md))) - (most (if (consp most-try) (car most-try) - (if most-try (car comps) ""))) - ;; Compare name and most, so we can determine if name is - ;; a prefix of most, or something else. - (compare (compare-strings name nil nil - most nil nil completion-ignore-case)) - (ellipsis (if (char-displayable-p ?…) "…" "...")) - (determ (unless (or (eq t compare) (eq t most-try) - (= (setq compare (1- (abs compare))) - (length most))) - (concat open-bracket - (cond - ((= compare (length name)) - ;; Typical case: name is a prefix. - (substring most compare)) - ;; Don't bother truncating if it doesn't gain - ;; us at least 2 columns. - ((< compare (+ 2 (string-width ellipsis))) most) - (t (concat ellipsis (substring most compare)))) - close-bracket))) - ;;"-prospects" - more than one candidate - (prospects-len (+ (string-width - (or determ (concat open-bracket close-bracket))) - (string-width icomplete-separator) - (+ 2 (string-width ellipsis)) ;; take {…} into account - (string-width (buffer-string)))) - (prospects-max - ;; Max total length to use, including the minibuffer content. - (* (+ icomplete-prospects-height - ;; If the minibuffer content already uses up more than - ;; one line, increase the allowable space accordingly. - (/ prospects-len (window-width))) - (window-width))) - ;; Find the common prefix among `comps'. - ;; We can't use the optimization below because its assumptions - ;; aren't always true, e.g. when completion-cycling (bug#10850): - ;; (if (eq t (compare-strings (car comps) nil (length most) - ;; most nil nil completion-ignore-case)) - ;; ;; Common case. - ;; (length most) - ;; Else, use try-completion. - (prefix (when icomplete-hide-common-prefix - (try-completion "" comps))) - (prefix-len - (and (stringp prefix) - ;; Only hide the prefix if the corresponding info - ;; is already displayed via `most'. - (string-prefix-p prefix most t) - (length prefix))) ;;) - prospects comp limit) - (if (or (eq most-try t) (not (consp (cdr comps)))) - (setq prospects nil) - (when (member name comps) - ;; NAME is complete but not unique. This scenario poses - ;; following UI issues: - ;; - ;; - When `icomplete-hide-common-prefix' is non-nil, NAME - ;; is stripped empty. This would make the entry - ;; inconspicuous. - ;; - ;; - Due to sorting of completions, NAME may not be the - ;; first of the prospects and could be hidden deep in - ;; the displayed string. - ;; - ;; - Because of `icomplete-prospects-height' , NAME may - ;; not even be displayed to the user. - ;; - ;; To circumvent all the above problems, provide a visual - ;; cue to the user via an "empty string" in the try - ;; completion field. - (setq determ (concat open-bracket "" close-bracket))) - ;; Compute prospects for display. - (while (and comps (not limit)) - (setq comp - (if prefix-len (substring (car comps) prefix-len) (car comps)) - comps (cdr comps)) - (setq prospects-len - (+ (string-width comp) - (string-width icomplete-separator) - prospects-len)) - (if (< prospects-len prospects-max) - (push comp prospects) - (setq limit t)))) - (setq prospects (nreverse prospects)) - ;; Decorate first of the prospects. - (when prospects - (let ((first (copy-sequence (pop prospects)))) - (put-text-property 0 (length first) - 'face 'icomplete-first-match first) - (push first prospects))) - ;; Restore the base-size info, since completion-all-sorted-completions - ;; is cached. - (if last (setcdr last base-size)) - (if prospects - (concat determ - (if icomplete-vertical-mode " \n" "{") - (mapconcat 'identity prospects (if icomplete-vertical-mode - "\n" - icomplete-separator)) - (unless icomplete-vertical-mode - (concat (and limit (concat icomplete-separator ellipsis)) - "}"))) - (concat determ " [Matched]")))))) + name comps nil (length name) md))) + (most (if (consp most-try) (car most-try) + (if most-try (car comps) ""))) + ;; Compare name and most, so we can determine if name is + ;; a prefix of most, or something else. + (compare (compare-strings name nil nil + most nil nil completion-ignore-case)) + (ellipsis (if (char-displayable-p ?…) "…" "...")) + (determ (unless (or (eq t compare) (eq t most-try) + (= (setq compare (1- (abs compare))) + (length most))) + (concat open-bracket + (cond + ((= compare (length name)) + ;; Typical case: name is a prefix. + (substring most compare)) + ;; Don't bother truncating if it doesn't gain + ;; us at least 2 columns. + ((< compare (+ 2 (string-width ellipsis))) most) + (t (concat ellipsis (substring most compare)))) + close-bracket))) + ;;"-prospects" - more than one candidate + (prospects-len (+ (string-width + (or determ (concat open-bracket close-bracket))) + (string-width icomplete-separator) + (+ 2 (string-width ellipsis)) ;; take {…} into account + (string-width (buffer-string)))) + (prospects-max + ;; Max total length to use, including the minibuffer content. + (* (+ icomplete-prospects-height + ;; If the minibuffer content already uses up more than + ;; one line, increase the allowable space accordingly. + (/ prospects-len (window-width))) + (window-width))) + ;; Find the common prefix among `comps'. + ;; We can't use the optimization below because its assumptions + ;; aren't always true, e.g. when completion-cycling (bug#10850): + ;; (if (eq t (compare-strings (car comps) nil (length most) + ;; most nil nil completion-ignore-case)) + ;; ;; Common case. + ;; (length most) + ;; Else, use try-completion. + (prefix (when icomplete-hide-common-prefix + (try-completion "" comps))) + (prefix-len + (and (stringp prefix) + ;; Only hide the prefix if the corresponding info + ;; is already displayed via `most'. + (string-prefix-p prefix most t) + (length prefix))) ;;) + prospects comp limit) + (prog1 + (if (or (eq most-try t) (and (not icomplete-scroll) + (not (consp (cdr comps))))) + (concat determ " [Matched]") + (when (member name comps) + ;; NAME is complete but not unique. This scenario poses + ;; following UI issues: + ;; + ;; - When `icomplete-hide-common-prefix' is non-nil, NAME + ;; is stripped empty. This would make the entry + ;; inconspicuous. + ;; + ;; - Due to sorting of completions, NAME may not be the + ;; first of the prospects and could be hidden deep in + ;; the displayed string. + ;; + ;; - Because of `icomplete-prospects-height' , NAME may + ;; not even be displayed to the user. + ;; + ;; To circumvent all the above problems, provide a visual + ;; cue to the user via an "empty string" in the try + ;; completion field. + (setq determ (concat open-bracket "" close-bracket))) + (while (and comps (not limit)) + (setq comp + (if prefix-len (substring (car comps) prefix-len) (car comps)) + comps (cdr comps)) + (setq prospects-len + (+ (string-width comp) + (string-width icomplete-separator) + prospects-len)) + (if (< prospects-len prospects-max) + (push comp prospects) + (setq limit t))) + (setq prospects (nreverse prospects)) + ;; Decorate first of the prospects. + (when prospects + (let ((first (copy-sequence (pop prospects)))) + (put-text-property 0 (length first) + 'face 'icomplete-first-match first) + (push first prospects))) + (concat determ + "{" + (mapconcat 'identity prospects icomplete-separator) + (concat (and limit (concat icomplete-separator ellipsis)) + "}"))) + ;; Restore the base-size info, since completion-all-sorted-completions + ;; is cached. + (if last (setcdr last base-size)))))))) ;;; Iswitchb compatibility diff --git a/lisp/simple.el b/lisp/simple.el index cdd77f74c3e..6d216f74d91 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -4217,12 +4217,22 @@ impose the use of a shell (with its need to quote arguments)." (shell-command-on-region (point) (point) command output-buffer nil error-buffer))))))) +(defun max-mini-window-lines (&optional frame) + "Compute maximum number of lines for echo area in FRAME. +As defined by `max-mini-window-height'. FRAME defaults to the +selected frame. Result may be a floating-point number, +i.e. include a fractional number of lines." + (cond ((floatp max-mini-window-height) (* (frame-height frame) + max-mini-window-height)) + ((integerp max-mini-window-height) max-mini-window-height) + (t 1))) + (defun display-message-or-buffer (message &optional buffer-name action frame) "Display MESSAGE in the echo area if possible, otherwise in a pop-up buffer. MESSAGE may be either a string or a buffer. A pop-up buffer is displayed using `display-buffer' if MESSAGE is too long -for maximum height of the echo area, as defined by `max-mini-window-height' +for maximum height of the echo area, as defined by `max-mini-window-lines' if `resize-mini-windows' is non-nil. Returns either the string shown in the echo area, or when a pop-up @@ -4261,14 +4271,7 @@ and are used only if a pop-up buffer is displayed." (cond ((= lines 0)) ((and (or (<= lines 1) (<= lines - (if resize-mini-windows - (cond ((floatp max-mini-window-height) - (* (frame-height) - max-mini-window-height)) - ((integerp max-mini-window-height) - max-mini-window-height) - (t - 1)) + (if resize-mini-windows (max-mini-window-lines) 1))) ;; Don't use the echo area if the output buffer is ;; already displayed in the selected frame. -- cgit v1.2.3 From fb1c5e4816ae55cd8fc5387624a94c9c648f6f72 Mon Sep 17 00:00:00 2001 From: João Távora Date: Tue, 25 May 2021 22:40:40 +0100 Subject: Add annotation capability to icomplete-vertical-mode Co-authored-by Daniel Mendler * lisp/icomplete.el (icomplete--affixate): New helper. (icomplete--render-vertical): Use it. Rework. (icomplete-completions): Pass md to icomplete--render-vertical. --- lisp/icomplete.el | 61 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 10 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index f813a1776e8..99896a48223 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -717,7 +717,30 @@ See `icomplete-mode' and `minibuffer-setup-hook'." (safe-length completion-all-sorted-completions)))))) (overlay-put icomplete-overlay 'after-string text)))))))) -(cl-defun icomplete--render-vertical (comps &aux scroll-above scroll-below) +(defun icomplete--affixate (md prospects) + "Affixate PROSPECTS given completion metadata MD. +Return a list of (COMP PREFIX SUFFIX)." + (let ((aff-fun (or (completion-metadata-get md 'affixation-function) + (plist-get completion-extra-properties :affixation-function))) + (ann-fun (or (completion-metadata-get md 'annotation-function) + (plist-get completion-extra-properties :annotation-function)))) + (cond (aff-fun + (funcall aff-fun prospects)) + (ann-fun + (mapcar + (lambda (comp) + (let ((suffix (or (funcall ann-fun comp) ""))) + (list comp "" + ;; The default completion UI adds the + ;; `completions-annotations' face if no + ;; other faces are present. + (if (text-property-not-all 0 (length suffix) 'face nil suffix) + suffix + (propertize suffix 'face 'completions-annotations))))) + prospects)) + (prospects)))) + +(cl-defun icomplete--render-vertical (comps md &aux scroll-above scroll-below) ;; Welcome to loopapalooza! ;; ;; First, be mindful of `icomplete-scroll' and manual scrolls. If @@ -771,14 +794,32 @@ See `icomplete-mode' and `minibuffer-setup-hook'." finally (setq scroll-below scroll-below-aux)) ;; Now figure out spacing and layout ;; - (let ((selected (substring (car comps)))) - (add-face-text-property 0 (length selected) - 'icomplete-selected-match 'append selected) - (concat " " icomplete-separator - (mapconcat - #'identity - (nconc scroll-above (list selected) scroll-below) - icomplete-separator)))) + (cl-loop + with selected = (substring (car comps)) + initially (add-face-text-property 0 (length selected) + 'icomplete-selected-match 'append selected) + with torender = (nconc scroll-above (list selected) scroll-below) + with triplets = (icomplete--affixate md torender) + initially (when (eq triplets torender) + (cl-return-from icomplete--render-vertical + (concat + " \n" + (mapconcat #'identity torender icomplete-separator)))) + for (comp prefix) in triplets + maximizing (length prefix) into max-prefix-len + maximizing (length comp) into max-comp-len + finally return + ;; Finally, render + ;; + (concat + " \n" + (cl-loop for (comp prefix suffix) in triplets + concat prefix + concat (make-string (- max-prefix-len (length prefix)) ? ) + concat comp + concat (make-string (- max-comp-len (length comp)) ? ) + concat suffix + concat icomplete-separator)))) ;;;_ > icomplete-completions (name candidates predicate require-match) (defun icomplete-completions (name candidates predicate require-match) @@ -824,7 +865,7 @@ matches exist." (progn ;;(debug (format "Candidates=%S field=%S" candidates name)) (format " %sNo matches%s" open-bracket close-bracket)) (if icomplete-vertical-mode - (icomplete--render-vertical comps) + (icomplete--render-vertical comps md) (let* ((last (if (consp comps) (last comps))) ;; Save the "base size" encoded in `comps' then ;; removing making `comps' a proper list. -- cgit v1.2.3 From 8d5b7f519f18ed73f26adff275e3bd580bacf36c Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sat, 5 Jun 2021 03:56:33 +0300 Subject: Make icomplete less blinky and more responsive * lisp/icomplete.el (icomplete-pre-command-hook, icomplete-tidy): Remove, update the callers (https://lists.gnu.org/archive/html/emacs-devel/2021-06/msg00111.html). (icomplete-compute-delay): Change the default to 150ms. (icomplete-max-delay-chars): Change the default to 2. --- etc/NEWS | 10 ++++++++++ lisp/icomplete.el | 18 ++---------------- 2 files changed, 12 insertions(+), 16 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/etc/NEWS b/etc/NEWS index d10fc5f2a1d..e782603f0b2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -549,6 +549,16 @@ Icomplete, completions are rotated and selection kept at the top. When used with Fido, completions scroll like a typical dropdown widget. +*** Default value of 'icomplete-compute-delay has been changed to 0.15 s. + +*** Default value of 'icomplete-max-delay-chars' has been changed to 2. + +*** Reduced blinking while completing the next completions set. +Icomplete doesn't hide the hint with the previously computed +completions anymore when compute delay is in effect, or the previous +computation has been aborted by input. Instead it shows the previous +completions until the new ones are ready. + --- ** Specific warnings can now be disabled from the warning buffer. When a warning is displayed to the user, the resulting buffer now has diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 99896a48223..03a191cb0b6 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -115,7 +115,7 @@ Otherwise this should be a list of the completion tables (e.g., :type 'integer :version "26.1") -(defcustom icomplete-compute-delay .3 +(defcustom icomplete-compute-delay .15 "Completions-computation stall, used only with large-number completions. See `icomplete-delay-completions-threshold'." :type 'number) @@ -124,7 +124,7 @@ See `icomplete-delay-completions-threshold'." "Pending-completions number over which to apply `icomplete-compute-delay'." :type 'integer) -(defcustom icomplete-max-delay-chars 3 +(defcustom icomplete-max-delay-chars 2 "Maximum number of initial chars to apply `icomplete-compute-delay'." :type 'integer) @@ -158,10 +158,6 @@ icompletion is occurring." "Initial input in the minibuffer when icomplete-mode was activated. Used to implement the option `icomplete-show-matches-on-no-input'.") -(defun icomplete-pre-command-hook () - (let ((non-essential t)) - (icomplete-tidy))) - (defun icomplete-post-command-hook () (let ((non-essential t)) ;E.g. don't prompt for password! (icomplete-exhibit))) @@ -490,7 +486,6 @@ Usually run by inclusion in `minibuffer-setup-hook'." (setq icomplete--scrolled-completions nil) (use-local-map (make-composed-keymap icomplete-minibuffer-map (current-local-map))) - (add-hook 'pre-command-hook #'icomplete-pre-command-hook nil t) (add-hook 'post-command-hook #'icomplete-post-command-hook nil t) (run-hooks 'icomplete-minibuffer-setup-hook))) @@ -504,7 +499,6 @@ Usually run by inclusion in `minibuffer-setup-hook'." (setq icomplete--in-region-buffer nil) (delete-overlay icomplete-overlay) (kill-local-variable 'completion-show-inline-help) - (remove-hook 'pre-command-hook 'icomplete-pre-command-hook t) (remove-hook 'post-command-hook 'icomplete-post-command-hook t) (message nil))) (when (and completion-in-region-mode @@ -516,7 +510,6 @@ Usually run by inclusion in `minibuffer-setup-hook'." (unless (memq icomplete-minibuffer-map (cdr tem)) (setcdr tem (make-composed-keymap icomplete-minibuffer-map (cdr tem))))) - (add-hook 'pre-command-hook 'icomplete-pre-command-hook nil t) (add-hook 'post-command-hook 'icomplete-post-command-hook nil t))) (defun icomplete--sorted-completions () @@ -640,13 +633,6 @@ resized depends on `resize-mini-windows'." ;;;_* Completion -;;;_ > icomplete-tidy () -(defun icomplete-tidy () - "Remove completions display (if any) prior to new user input. -Should be run in on the minibuffer `pre-command-hook'. -See `icomplete-mode' and `minibuffer-setup-hook'." - (delete-overlay icomplete-overlay)) - ;;;_ > icomplete-exhibit () (defun icomplete-exhibit () "Insert Icomplete completions display. -- cgit v1.2.3 From 45d711a356b4c5e75d0b6e4391313ca34f57b4bb Mon Sep 17 00:00:00 2001 From: João Távora Date: Sat, 5 Jun 2021 21:46:59 +0100 Subject: Consider environment vars in Fido's directory-aware RET binding Fixes: bug#48782 * lisp/icomplete.el (icomplete-fido-ret): Consider environment variables in dir expansion. --- lisp/icomplete.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 03a191cb0b6..08b4ef2030a 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -331,7 +331,8 @@ require user confirmation." (file-name-directory (icomplete--field-string)))) (current (car completion-all-sorted-completions)) (probe (and dir current - (expand-file-name (directory-file-name current) dir)))) + (expand-file-name (directory-file-name current) + (substitute-env-vars dir))))) (cond ((and probe (file-directory-p probe) (not (string= current "./"))) (icomplete-force-complete)) (t -- cgit v1.2.3 From 8ebd8e1fea1d0d925850db97b64bf13a6a1f698b Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Wed, 30 Jun 2021 22:17:01 +0200 Subject: In files that use allout use it for all headings * lisp/allout.el: Don't prefix regular comments with three semicolons. * lisp/icomplete.el: Use allout syntax for all headings. * lisp/net/eudc.el: Use allout syntax for all headings. --- lisp/allout.el | 8 ++++---- lisp/icomplete.el | 8 ++++---- lisp/net/eudc.el | 4 +++- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/allout.el b/lisp/allout.el index 1605ce2ce33..0625ea68abe 100644 --- a/lisp/allout.el +++ b/lisp/allout.el @@ -2490,10 +2490,10 @@ We skip anomalous low-level topics, a la `allout-aberrant-container-p'." ;;;_ - Subtree Charting ;;;_ " These routines either produce or assess charts, which are -;;; nested lists of the locations of topics within a subtree. -;;; -;;; Charts enable efficient subtree navigation by providing a reusable basis -;;; for elaborate, compound assessment and adjustment of a subtree. +;; nested lists of the locations of topics within a subtree. +;; +;; Charts enable efficient subtree navigation by providing a reusable basis +;; for elaborate, compound assessment and adjustment of a subtree. ;;;_ > allout-chart-subtree (&optional levels visible orig-depth prev-depth) (defun allout-chart-subtree (&optional levels visible orig-depth prev-depth) diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 08b4ef2030a..26698c43cfd 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -276,8 +276,8 @@ Last entry becomes the first and can be selected with (setcdr last-but-one (cdr (cdr last-but-one))))) (completion--cache-all-sorted-completions beg end comps))) -;;; Helpers for `fido-mode' (or `ido-mode' emulation) -;;; +;;;_* Helpers for `fido-mode' (or `ido-mode' emulation) + (defun icomplete-fido-kill () "Kill line or current completion, like `ido-mode'. If killing to the end of line make sense, call `kill-line', @@ -966,7 +966,7 @@ matches exist." ;; is cached. (if last (setcdr last base-size)))))))) -;;; Iswitchb compatibility +;;;_* Iswitchb compatibility ;; We moved Iswitchb to `obsolete' in 24.4, but autoloads in files in ;; `obsolete' aren't obeyed (since that would encourage people to keep using @@ -981,7 +981,7 @@ matches exist." (provide 'icomplete) -;;_* Local emacs vars. +;;;_* Local emacs vars. ;;Local variables: ;;allout-layout: (-2 :) ;;End: diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index 425217cf65c..6459c52afee 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -1129,7 +1129,9 @@ queries the server for the existing fields and displays a corresponding form." (cons "Directory Servers" (easy-menu-create-menu "Directory Servers" (cdr (eudc-menu)))))) -;;; Load time initializations : +;;}}} + +;;{{{ Load time initializations ;; Load the options file (if (and (not noninteractive) -- cgit v1.2.3 From 9b318d5c58fef6faf344f0377cbf169b5e1f0e09 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 4 Jul 2021 04:38:35 +0300 Subject: Speed up fido-mode * lisp/icomplete.el (icomplete-completions): Speed up fido-mode (bug#48841). --- lisp/icomplete.el | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 26698c43cfd..576fced015a 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -859,13 +859,16 @@ matches exist." (base-size (prog1 (cdr last) (if last (setcdr last nil)))) (most-try - (if (and base-size (> base-size 0)) + ;; icomplete-hide-common-prefix logic is used + ;; unconditionally when there is single match. + (when (or icomplete-hide-common-prefix (not (cdr comps))) + (if (and base-size (> base-size 0)) + (completion-try-completion + name candidates predicate (length name) md) + ;; If the `comps' are 0-based, the result should be + ;; the same with `comps'. (completion-try-completion - name candidates predicate (length name) md) - ;; If the `comps' are 0-based, the result should be - ;; the same with `comps'. - (completion-try-completion - name comps nil (length name) md))) + name comps nil (length name) md)))) (most (if (consp most-try) (car most-try) (if most-try (car comps) ""))) ;; Compare name and most, so we can determine if name is -- cgit v1.2.3 From 513539524e947a231ee0b2fc307d4afe3969c1ef Mon Sep 17 00:00:00 2001 From: Gabriel do Nascimento Ribeiro Date: Mon, 19 Jul 2021 18:04:25 +0200 Subject: Use 'remember-buffer' in remember.el doc strings. * lisp/textmodes/remember.el (remember-initial-contents) (remember-before-remember-hook, remember-destroy): Refer to `remember-buffer'. * lisp/textmodes/remember.el (remember-buffer): Make into defcustom (bug#49373). --- etc/NEWS | 5 +++++ lisp/icomplete.el | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/etc/NEWS b/etc/NEWS index e241b512b6a..42869f44dcf 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -581,6 +581,11 @@ indentation is done using SMIE or with the old ad-hoc code. ** Icomplete +--- +*** New user option 'icomplete-matches-format'. +This allows controlling the current/total number of matches for the +prompt prefix. + +++ *** New minor mode 'icomplete-vertical-mode', alias 'fido-vertical-mode'. This mode is intended to be used with Icomplete ('M-x icomplete-mode') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 576fced015a..adea1505fd2 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -97,6 +97,12 @@ Otherwise this should be a list of the completion tables (e.g., :type '(choice (const :tag "All" t) (repeat function))) +(defcustom icomplete-matches-format "%s/%s " + "Format of the current/total number of matches for the prompt prefix." + :version "28.1" + :type '(choice (const :tag "No prefix" nil) + (string :tag "Prefix format string"))) + (defface icomplete-first-match '((t :weight bold)) "Face used by Icomplete for highlighting first match." :version "24.4") @@ -696,12 +702,12 @@ See `icomplete-mode' and `minibuffer-setup-hook'." (overlay-put icomplete-overlay 'before-string (and icomplete-scroll - (let ((past (length icomplete--scrolled-past))) - (format - "%s/%s " - (1+ past) - (+ past - (safe-length completion-all-sorted-completions)))))) + icomplete-matches-format + (let* ((past (length icomplete--scrolled-past)) + (current (1+ past)) + (total (+ past (safe-length + completion-all-sorted-completions)))) + (format icomplete-matches-format current total)))) (overlay-put icomplete-overlay 'after-string text)))))))) (defun icomplete--affixate (md prospects) -- cgit v1.2.3 From e6f3a4dc6cd4ffca9b8b2ea0c9271f832df07e3e Mon Sep 17 00:00:00 2001 From: João Távora Date: Sun, 15 Aug 2021 09:12:23 +0100 Subject: Fix bug#50063 when using icomplete-fido-kill with C-x p p C-x p p utilizes a completion table "category" which is 'project-file' icomplete-fido-kill only functioned for 'buffer' and 'file', and failed with a non-informative message when something else was used. * lisp/icomplete.el (icomplete-fido-kill): Support 'project-file' class. Use cl-case, instead of pcase. --- lisp/icomplete.el | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index adea1505fd2..cd1979d04ad 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -298,18 +298,21 @@ require user confirmation." (call-interactively 'kill-line) (let* ((all (completion-all-sorted-completions)) (thing (car all)) + (cat (icomplete--category)) (action - (pcase (icomplete--category) - (`buffer + (cl-case cat + (buffer (lambda () (when (yes-or-no-p (concat "Kill buffer " thing "? ")) (kill-buffer thing)))) - (`file + ((project-file file) (lambda () (let* ((dir (file-name-directory (icomplete--field-string))) (path (expand-file-name thing dir))) (when (yes-or-no-p (concat "Delete file " path "? ")) - (delete-file path) t))))))) + (delete-file path) t)))) + (t + (error "Sorry, don't know how to kill things for `%s'" cat))))) (when (let (;; Allow `yes-or-no-p' to work and don't let it ;; `icomplete-exhibit' anything. (enable-recursive-minibuffers t) -- cgit v1.2.3 From a126c06b0a5d585e7d7dd6d952b3f99447d15fc2 Mon Sep 17 00:00:00 2001 From: João Távora Date: Mon, 16 Aug 2021 23:15:12 +0100 Subject: Make icomplete-vertical-mode take immediate effect (bug#49075) * etc/NEWS: Mention change. * lisp/icomplete.el (icomplete-vertical-mode): (fido-vertical-mode): Tweak docstring. Turn on icomplete-mode. and fido-mdoe --- etc/NEWS | 15 ++++++++------- lisp/icomplete.el | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/etc/NEWS b/etc/NEWS index 3ccef6683a5..aaff30bfa92 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -655,13 +655,14 @@ This allows controlling the current/total number of matches for the prompt prefix. +++ -*** New minor mode 'icomplete-vertical-mode', alias 'fido-vertical-mode'. -This mode is intended to be used with Icomplete ('M-x icomplete-mode') -or Fido ('M-x fido-mode'), to display the list of completions -candidates vertically instead of horizontally. When used with -Icomplete, completions are rotated and selection kept at the top. -When used with Fido, completions scroll like a typical dropdown -widget. +*** New minor modes 'icomplete-vertical-mode' and 'fido-vertical-mode' +These modes are modify Icomplete ('M-x icomplete-mode') and Fido ('M-x +fido-mode'), to display completions candidates vertically instead of +horizontally. In Icomplete, completions are rotated and selection +kept at the top. In Fido, completions scroll like a typical dropdown +widget. Both these new minor modes will first turn on their +respective non-vertical counterparts first, if they are not on +already. --- *** Default value of 'icomplete-compute-delay' has been changed to 0.15 s. diff --git a/lisp/icomplete.el b/lisp/icomplete.el index cd1979d04ad..e06b33e43bb 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -626,6 +626,8 @@ Usually run by inclusion in `minibuffer-setup-hook'." (define-minor-mode icomplete-vertical-mode "Toggle vertical candidate display in `icomplete-mode' or `fido-mode'. +If none of these modes are on, turn on `icomplete-mode'. + As many completion candidates as possible are displayed, depending on the value of `max-mini-window-height', and the way the mini-window is resized depends on `resize-mini-windows'." @@ -633,10 +635,21 @@ resized depends on `resize-mini-windows'." (remove-hook 'icomplete-minibuffer-setup-hook #'icomplete--vertical-minibuffer-setup) (when icomplete-vertical-mode + (unless icomplete-mode + (icomplete-mode 1)) (add-hook 'icomplete-minibuffer-setup-hook #'icomplete--vertical-minibuffer-setup))) -(defalias 'fido-vertical-mode 'icomplete-vertical-mode) +;;;###autoload +(define-minor-mode fido-vertical-mode + "Toggle vertical candidate display in `fido-mode'. +When turning on, if non-vertical `fido-mode' is off, turn it on. +If it's on, just add the vertical display." + :global t + (icomplete-vertical-mode -1) + (when fido-vertical-mode + (unless fido-mode (fido-mode 1)) + (icomplete-vertical-mode 1))) -- cgit v1.2.3 From 96bbd6f0a7f20ae77bcd8a477b54b11ba5b42cc6 Mon Sep 17 00:00:00 2001 From: João Távora Date: Tue, 17 Aug 2021 12:48:37 +0100 Subject: Jump to first,last completion with M-<, M-> in icomplete-vertical-mode Fixes: bug#49005 Co-authored-by: Simon Lang * lisp/icomplete.el (icomplete-backward-completions): Return non-nil iff something was stepped. Ajust docstring. (icomplete-forward-completions): Adjust docstring. (icomplete-vertical-goto-first, icomplete-vertical-goto-last): New commands. (icomplete-vertical-mode-minibuffer-map): Bind new commands to M-< and M->. --- lisp/icomplete.el | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index e06b33e43bb..96b7e0f2014 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -249,7 +249,8 @@ the default otherwise." (defun icomplete-forward-completions () "Step forward completions by one entry. Second entry becomes the first and can be selected with -`icomplete-force-complete-and-exit'." +`icomplete-force-complete-and-exit'. +Return non-nil iff something was stepped." (interactive) (let* ((beg (icomplete--field-beg)) (end (icomplete--field-end)) @@ -266,21 +267,35 @@ Second entry becomes the first and can be selected with (defun icomplete-backward-completions () "Step backward completions by one entry. Last entry becomes the first and can be selected with -`icomplete-force-complete-and-exit'." +`icomplete-force-complete-and-exit'. +Return non-nil iff something was stepped." (interactive) (let* ((beg (icomplete--field-beg)) (end (icomplete--field-end)) (comps (completion-all-sorted-completions beg end)) - last-but-one) - (cond ((and icomplete-scroll icomplete--scrolled-past) - (push (pop icomplete--scrolled-past) comps) - (setq icomplete--scrolled-completions comps)) - ((and (not icomplete-scroll) - (consp (cdr (setq last-but-one (last comps 2))))) - ;; At least two elements in comps - (push (car (cdr last-but-one)) comps) - (setcdr last-but-one (cdr (cdr last-but-one))))) - (completion--cache-all-sorted-completions beg end comps))) + last-but-one) + (prog1 + (cond ((and icomplete-scroll icomplete--scrolled-past) + (push (pop icomplete--scrolled-past) comps) + (setq icomplete--scrolled-completions comps)) + ((and (not icomplete-scroll) + (consp (cdr (setq last-but-one (last comps 2))))) + ;; At least two elements in comps + (push (car (cdr last-but-one)) comps) + (setcdr last-but-one (cdr (cdr last-but-one))))) + (completion--cache-all-sorted-completions beg end comps)))) + +(defun icomplete-vertical-goto-first () + "Go to first completions entry when `icomplete-scroll' is non-nil." + (interactive) + (unless icomplete-scroll (error "Only works with `icomplete-scroll'")) + (while (icomplete-backward-completions))) + +(defun icomplete-vertical-goto-last () + "Go to last completions entry when `icomplete-scroll' is non-nil." + (interactive) + (unless icomplete-scroll (error "Only works with `icomplete-scroll'")) + (while (icomplete-forward-completions))) ;;;_* Helpers for `fido-mode' (or `ido-mode' emulation) @@ -609,6 +624,8 @@ Usually run by inclusion in `minibuffer-setup-hook'." (let ((map (make-sparse-keymap))) (define-key map (kbd "C-n") 'icomplete-forward-completions) (define-key map (kbd "C-p") 'icomplete-backward-completions) + (define-key map (kbd "M-<") 'icomplete-vertical-goto-first) + (define-key map (kbd "M->") 'icomplete-vertical-goto-last) map) "Keymap used by `icomplete-vertical-mode' in the minibuffer.") -- cgit v1.2.3 From e6fb7e44cc7da97f7c29246dbff89009de9a4633 Mon Sep 17 00:00:00 2001 From: João Távora Date: Tue, 17 Aug 2021 13:06:06 +0100 Subject: Bind and in icomplete-vertical-mode Suggested by Ergus * lisp/icomplete.el (icomplete-vertical-mode-minibuffer-map): Bind and --- lisp/icomplete.el | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 96b7e0f2014..81fc6ff03ca 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -624,6 +624,8 @@ Usually run by inclusion in `minibuffer-setup-hook'." (let ((map (make-sparse-keymap))) (define-key map (kbd "C-n") 'icomplete-forward-completions) (define-key map (kbd "C-p") 'icomplete-backward-completions) + (define-key map (kbd "") 'icomplete-forward-completions) + (define-key map (kbd "") 'icomplete-backward-completions) (define-key map (kbd "M-<") 'icomplete-vertical-goto-first) (define-key map (kbd "M->") 'icomplete-vertical-goto-last) map) -- cgit v1.2.3 From 2be8e2ffc9dff0b43cc6beaac9084791e2f62be6 Mon Sep 17 00:00:00 2001 From: João Távora Date: Thu, 19 Aug 2021 00:48:26 +0100 Subject: Section by 'group-function' in Icomplete and Fido's vertical modes Fixes: bug#48545 * lisp/icomplete.el (icomplete--augment): Rewrite from icomplete--affixate. (icomplete--render-vertical): Rework. (icomplete--vertical-minibuffer-setup): Separator is hardcoded "\n", no need to set. --- lisp/icomplete.el | 149 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 55 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 81fc6ff03ca..73aaa3196a9 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -111,6 +111,9 @@ Otherwise this should be a list of the completion tables (e.g., "Face used by `icomplete-vertical-mode' for the selected candidate." :version "24.4") +(defface icomplete-section '((t :inherit shadow :slant italic)) + "Face used by `icomplete-vertical-mode' for the section title.") + ;;;_* User Customization variables (defcustom icomplete-prospects-height 2 ;; We used to compute how many lines 100 characters would take in @@ -635,8 +638,7 @@ Usually run by inclusion in `minibuffer-setup-hook'." "Setup the minibuffer for vertical display of completion candidates." (use-local-map (make-composed-keymap icomplete-vertical-mode-minibuffer-map (current-local-map))) - (setq-local icomplete-separator "\n" - icomplete-hide-common-prefix nil + (setq-local icomplete-hide-common-prefix nil ;; Ask `icomplete-completions' to return enough completions candidates. icomplete-prospects-height 25 redisplay-adhoc-scroll-in-resize-mini-windows nil)) @@ -745,14 +747,21 @@ See `icomplete-mode' and `minibuffer-setup-hook'." (format icomplete-matches-format current total)))) (overlay-put icomplete-overlay 'after-string text)))))))) -(defun icomplete--affixate (md prospects) - "Affixate PROSPECTS given completion metadata MD. -Return a list of (COMP PREFIX SUFFIX)." - (let ((aff-fun (or (completion-metadata-get md 'affixation-function) - (plist-get completion-extra-properties :affixation-function))) - (ann-fun (or (completion-metadata-get md 'annotation-function) - (plist-get completion-extra-properties :annotation-function)))) - (cond (aff-fun +(defun icomplete--augment (md prospects) + "Augment completion strings in PROSPECTS with completion metadata MD. +Return a list of strings (COMP PREFIX SUFFIX SECTION). PREFIX +and SUFFIX, if non-nil are obtained from `affixation-function' or +`annotation-function' metadata. SECTION is obtained from +`group-function'. Consecutive `equal' sections are avoided. +COMP is the element in PROSPECTS or a transformation also given +by `group-function''s second \"transformation\" protocol." + (let* ((aff-fun (or (completion-metadata-get md 'affixation-function) + (plist-get completion-extra-properties :affixation-function))) + (ann-fun (or (completion-metadata-get md 'annotation-function) + (plist-get completion-extra-properties :annotation-function))) + (grp-fun (completion-metadata-get md 'group-function)) + (annotated + (cond (aff-fun (funcall aff-fun prospects)) (ann-fun (mapcar @@ -766,9 +775,24 @@ Return a list of (COMP PREFIX SUFFIX)." suffix (propertize suffix 'face 'completions-annotations))))) prospects)) - (prospects)))) - -(cl-defun icomplete--render-vertical (comps md &aux scroll-above scroll-below) + (t (mapcar #'list prospects))))) + (if grp-fun + (cl-loop with section = nil + for (c prefix suffix) in annotated + for selectedp = (get-text-property 0 'icomplete-selected c) + for tr = (propertize (or (funcall grp-fun c t) c) + 'icomplete-selected selectedp) + if (not (equal section (setq section (funcall grp-fun c nil)))) + collect (list tr prefix suffix section) + else collect (list tr prefix suffix )) + annotated))) + +(cl-defun icomplete--render-vertical + (comps md &aux scroll-above scroll-below + (total-space ; number of mini-window lines available + (1- (min + icomplete-prospects-height + (truncate (max-mini-window-lines) 1))))) ;; Welcome to loopapalooza! ;; ;; First, be mindful of `icomplete-scroll' and manual scrolls. If @@ -776,11 +800,11 @@ Return a list of (COMP PREFIX SUFFIX)." ;; are: ;; ;; - both nil, there is no manual scroll; - ;; - both non-nil, there is a healthy manual scroll the doesn't need + ;; - both non-nil, there is a healthy manual scroll that doesn't need ;; to be readjusted (user just moved around the minibuffer, for ;; example)l ;; - non-nil and nil, respectively, a refiltering took place and we - ;; need attempt to readjust them to the new filtered `comps'. + ;; may need to readjust them to the new filtered `comps'. (when (and icomplete-scroll icomplete--scrolled-completions (null icomplete--scrolled-past)) @@ -802,52 +826,67 @@ Return a list of (COMP PREFIX SUFFIX)." ;; positions. (cl-loop with preds = icomplete--scrolled-past with succs = (cdr comps) - with max-lines = (1- (min - icomplete-prospects-height - (truncate (max-mini-window-lines) 1))) - with max-above = (- max-lines - 1 - (cl-loop for (_ . r) on comps - repeat (truncate max-lines 2) - while (listp r) - count 1)) - repeat max-lines + with space-above = (- total-space + 1 + (cl-loop for (_ . r) on comps + repeat (truncate total-space 2) + while (listp r) + count 1)) + repeat total-space for neighbour = nil - if (and preds (> max-above 0)) do + if (and preds (> space-above 0)) do (push (setq neighbour (pop preds)) scroll-above) - (cl-decf max-above) + (cl-decf space-above) else if (consp succs) collect (setq neighbour (pop succs)) into scroll-below-aux while neighbour finally (setq scroll-below scroll-below-aux)) - ;; Now figure out spacing and layout - ;; - (cl-loop - with selected = (substring (car comps)) - initially (add-face-text-property 0 (length selected) - 'icomplete-selected-match 'append selected) - with torender = (nconc scroll-above (list selected) scroll-below) - with triplets = (icomplete--affixate md torender) - initially (when (eq triplets torender) - (cl-return-from icomplete--render-vertical - (concat - " \n" - (mapconcat #'identity torender icomplete-separator)))) - for (comp prefix) in triplets - maximizing (length prefix) into max-prefix-len - maximizing (length comp) into max-comp-len - finally return - ;; Finally, render - ;; - (concat - " \n" - (cl-loop for (comp prefix suffix) in triplets - concat prefix - concat (make-string (- max-prefix-len (length prefix)) ? ) - concat comp - concat (make-string (- max-comp-len (length comp)) ? ) - concat suffix - concat icomplete-separator)))) + ;; Halfway there... + (let* ((selected (propertize (car comps) 'icomplete-selected t)) + (chosen (append scroll-above (list selected) scroll-below)) + (tuples (icomplete--augment md chosen)) + max-prefix-len max-comp-len lines nsections) + (add-face-text-property 0 (length selected) + 'icomplete-selected-match 'append selected) + ;; Figure out parameters for horizontal spacing + (cl-loop + for (comp prefix) in tuples + maximizing (length prefix) into max-prefix-len-aux + maximizing (length comp) into max-comp-len-aux + finally (setq max-prefix-len max-prefix-len-aux + max-comp-len max-comp-len-aux)) + ;; Serialize completions and section titles into a list + ;; of lines to render + (cl-loop + for (comp prefix suffix section) in tuples + when section + collect (propertize section 'face 'icomplete-section) into lines-aux + and count 1 into nsections-aux + when (get-text-property 0 'icomplete-selected comp) + do (add-face-text-property 0 (length comp) + 'icomplete-selected-match 'append comp) + collect (concat prefix + (make-string (- max-prefix-len (length prefix)) ? ) + comp + (make-string (- max-comp-len (length comp)) ? ) + suffix) + into lines-aux + finally (setq lines lines-aux + nsections nsections-aux)) + ;; Kick out some lines from the beginning due to extra sections. + ;; This hopes to keep the selected entry more or less in the + ;; middle of the dropdown-like widget when `icomplete-scroll' is + ;; t. Funky, but at least I didn't use `cl-loop' + (setq lines + (nthcdr + (cond ((<= (length lines) total-space) 0) + ((> (length scroll-above) (length scroll-below)) nsections) + (t (min (ceiling nsections 2) (length scroll-above)))) + lines)) + ;; At long last, render final string return value. This may still + ;; kick out lines at the end. + (concat " \n" + (cl-loop for l in lines repeat total-space concat l concat "\n")))) ;;;_ > icomplete-completions (name candidates predicate require-match) (defun icomplete-completions (name candidates predicate require-match) -- cgit v1.2.3 From 37f0ea99f8dc967f506b70f0d9ccb2a8fe76ca22 Mon Sep 17 00:00:00 2001 From: João Távora Date: Thu, 19 Aug 2021 11:29:14 +0100 Subject: ; Correct :version tag of icomplete-selected-match face * lisp/icomplete.el (icomplete-selected-match): Fix :version --- lisp/icomplete.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 73aaa3196a9..ee34d85514b 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -109,7 +109,7 @@ Otherwise this should be a list of the completion tables (e.g., (defface icomplete-selected-match '((t :inherit highlight)) "Face used by `icomplete-vertical-mode' for the selected candidate." - :version "24.4") + :version "28.1") (defface icomplete-section '((t :inherit shadow :slant italic)) "Face used by `icomplete-vertical-mode' for the section title.") -- cgit v1.2.3 From 787fa7a8ab3ccf12c0e7e4efafd7506999071ea5 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 19 Aug 2021 15:29:49 +0300 Subject: Minor doc fixes in icomplete.el * lisp/icomplete.el (icomplete-section): Add :version. (icomplete--augment): Doc fix. --- lisp/icomplete.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index ee34d85514b..84073933894 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -112,7 +112,8 @@ Otherwise this should be a list of the completion tables (e.g., :version "28.1") (defface icomplete-section '((t :inherit shadow :slant italic)) - "Face used by `icomplete-vertical-mode' for the section title.") + "Face used by `icomplete-vertical-mode' for the section title." + :version "28.1") ;;;_* User Customization variables (defcustom icomplete-prospects-height 2 @@ -750,7 +751,7 @@ See `icomplete-mode' and `minibuffer-setup-hook'." (defun icomplete--augment (md prospects) "Augment completion strings in PROSPECTS with completion metadata MD. Return a list of strings (COMP PREFIX SUFFIX SECTION). PREFIX -and SUFFIX, if non-nil are obtained from `affixation-function' or +and SUFFIX, if non-nil, are obtained from `affixation-function' or `annotation-function' metadata. SECTION is obtained from `group-function'. Consecutive `equal' sections are avoided. COMP is the element in PROSPECTS or a transformation also given -- cgit v1.2.3 From fb81c8c3adf8633f2f617c82f6019aef630860c7 Mon Sep 17 00:00:00 2001 From: João Távora Date: Thu, 19 Aug 2021 23:54:51 +0100 Subject: Make icomplete-forward-completions O(1) when icomplete-scroll is t In particular, this makes the recently added icomplete-vertical-goto-last (bug#49005) be O(n) instead of O(n^2). That used to be almost unbearably slow for large n. * lisp/icomplete.el (icomplete-forward-completions): don't call last unless needed. --- lisp/icomplete.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lisp/icomplete.el') diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 84073933894..03616f9b6aa 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -258,14 +258,14 @@ Return non-nil iff something was stepped." (interactive) (let* ((beg (icomplete--field-beg)) (end (icomplete--field-end)) - (comps (completion-all-sorted-completions beg end)) - (last (last comps))) + (comps (completion-all-sorted-completions beg end))) (when (consp (cdr comps)) (cond (icomplete-scroll (push (pop comps) icomplete--scrolled-past) (setq icomplete--scrolled-completions comps)) (t - (setcdr (last comps) (cons (pop comps) (cdr last))))) + (let ((last (last comps))) + (setcdr (last comps) (cons (pop comps) (cdr last)))))) (completion--cache-all-sorted-completions beg end comps)))) (defun icomplete-backward-completions () -- cgit v1.2.3