Mercurial > hg > xemacs-beta
view lisp/list-mode.el @ 5882:bbe4146603db
Reduce regexp usage, now CL-oriented non-regexp code available, core Lisp
lisp/ChangeLog addition:
2015-04-01 Aidan Kehoe <kehoea@parhasard.net>
When calling #'string-match with a REGEXP without regular
expression special characters, call #'search, #'mismatch, #'find,
etc. instead, making our code less likely to side-effect other
functions' match data and a little faster.
* apropos.el (apropos-command):
* apropos.el (apropos):
Call (position ?\n ...) rather than (string-match "\n" ...) here.
* buff-menu.el:
* buff-menu.el (buffers-menu-omit-invisible-buffers):
Don't fire up the regexp engine just to check if a string starts
with a space.
* buff-menu.el (select-buffers-tab-buffers-by-mode):
Don't fire up the regexp engine just to compare mode basenames.
* buff-menu.el (format-buffers-tab-line):
* buff-menu.el (build-buffers-tab-internal): Moved to being a
label within the following.
* buff-menu.el (buffers-tab-items): Use the label.
* bytecomp.el (byte-compile-log-1):
Don't fire up the regexp engine just to look for a newline.
* cus-edit.el (get):
Ditto.
* cus-edit.el (custom-variable-value-create):
Ditto, but for a colon.
* descr-text.el (describe-text-sexp):
Ditto.
* descr-text.el (describe-char-unicode-data):
Use #'split-string-by-char given that we're just looking for a
semicolon.
* descr-text.el (describe-char):
Don't fire up the regexp engine just to look for a newline.
* disass.el (disassemble-internal):
Ditto.
* files.el (file-name-sans-extension):
Implement this using #'position.
* files.el (file-name-extension):
Correct this function's docstring, implement it in terms of
#'position.
* files.el (insert-directory):
Don't fire up the regexp engine to split a string by space; don't
reverse the list of switches, this is actually a longstand bug as
far as I can see.
* gnuserv.el (gnuserv-process-filter):
Use #'position here, instead of consing inside #'split-string
needlessly.
* gtk-file-dialog.el (gtk-file-dialog-update-dropdown):
Use #'split-string-by-char here, don't fire up #'split-string for
directory-sep-char.
* gtk-font-menu.el (hack-font-truename):
Implement this more cheaply in terms of #'find,
#'split-string-by-char, #'equal, rather than #'string-match,
#'split-string, #'string-equal.
* hyper-apropos.el (hyper-apropos-grok-functions):
* hyper-apropos.el (hyper-apropos-grok-variables):
Look for a newline using #'position rather than #'string-match in
these functions.
* info.el (Info-insert-dir):
* info.el (Info-insert-file-contents):
* info.el (Info-follow-reference):
* info.el (Info-extract-menu-node-name):
* info.el (Info-menu):
Look for fixed strings using #'position or #'search as appropriate
in this file.
* ldap.el (ldap-decode-string):
* ldap.el (ldap-encode-string):
#'encode-coding-string, #'decode-coding-string are always
available, don't check if they're fboundp.
* ldap.el (ldap-decode-address):
* ldap.el (ldap-encode-address):
Use #'split-string-by-char in these functions.
* lisp-mnt.el (lm-creation-date):
* lisp-mnt.el (lm-last-modified-date):
Don't fire up the regexp engine just to look for spaces in this file.
* menubar-items.el (default-menubar):
Use (not (mismatch ...)) rather than #'string-match here, for
simple regexp.
Use (search "beta" ...) rather than (string-match "beta" ...)
* menubar-items.el (sort-buffers-menu-alphabetically):
* menubar-items.el (sort-buffers-menu-by-mode-then-alphabetically):
* menubar-items.el (group-buffers-menu-by-mode-then-alphabetically):
Don't fire up the regexp engine to check if a string starts with
a space or an asterisk.
Use the more fine-grained results of #'compare-strings; compare
case-insensitively for the buffer menu.
* menubar-items.el (list-all-buffers):
* menubar-items.el (tutorials-menu-filter):
Use #'equal rather than #'string-equal, which, in this context,
has the drawback of not having a bytecode, and no redeeming
features.
* minibuf.el:
* minibuf.el (un-substitute-in-file-name):
Use #'count, rather than counting the occurences of $ using the
regexp engine.
* minibuf.el (read-file-name-internal-1):
Don't fire up the regexp engine to search for ?=.
* mouse.el (mouse-eval-sexp):
Check for newline with #'find.
* msw-font-menu.el (mswindows-reset-device-font-menus):
Split a string by newline with #'split-string-by-char.
* mule/japanese.el:
* mule/japanese.el ("Japanese"):
Use #'search rather than #'string-match; canoncase before
comparing; fix a bug I had introduced where I had been making case
insensitive comparisons where the case mattered.
* mule/korea-util.el (default-korean-keyboard):
Look for ?3 using #'find, not #'string-march.
* mule/korea-util.el (quail-hangul-switch-hanja):
Search for a fixed string using #'search.
* mule/mule-cmds.el (set-locale-for-language-environment):
#'position, #'substitute rather than #'string-match,
#'replace-in-string.
* newcomment.el (comment-make-extra-lines):
Use #'search rather than #'string-match for a simple string.
* package-get.el (package-get-remote-filename):
Use #'position when looking for ?@
* process.el (setenv):
* process.el (read-envvar-name):
Use #'position when looking for ?=.
* replace.el (map-query-replace-regexp):
Use #'split-string-by-char instead of using an inline
implementation of it.
* select.el (select-convert-from-cf-text):
* select.el (select-convert-from-cf-unicodetext):
Use #'position rather than #'string-match in these functions.
* setup-paths.el (paths-emacs-data-root-p):
Use #'search when looking for simple string.
* sound.el (load-sound-file):
Use #'split-string-by-char rather than an inline reimplementation
of same.
* startup.el (splash-screen-window-body):
* startup.el (splash-screen-tty-body):
Search for simple strings using #'search.
* version.el (emacs-version):
Ditto.
* x-font-menu.el (hack-font-truename):
Implement this more cheaply in terms of #'find,
#'split-string-by-char, #'equal, rather than #'string-match,
#'split-string, #'string-equal.
* x-font-menu.el (x-reset-device-font-menus-core):
Use #'split-string-by-char here.
* x-init.el (x-initialize-keyboard):
Search for a simple string using #'search.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Wed, 01 Apr 2015 14:28:20 +0100 |
parents | 89331fa1c819 |
children |
line wrap: on
line source
;;; list-mode.el --- Major mode for buffers containing lists of items ;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1996, 2000 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: extensions, dumped ;; This file is part of XEmacs. ;; XEmacs 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. ;; XEmacs 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 XEmacs. If not, see <http://www.gnu.org/licenses/>. ;;; Synched up with: Not synched ;;; Commentary: ;; This file is dumped with XEmacs. ;; Cleanup, merging with FSF by Ben Wing, January 1996 ;;; Code: (defvar list-mode-extent nil) (make-variable-buffer-local 'list-mode-extent) (defvar list-mode-map nil "Local map for buffers containing lists of items.") (or list-mode-map (let ((map (setq list-mode-map (make-sparse-keymap 'list-mode-map)))) (suppress-keymap map) (define-key map 'button2up 'list-mode-item-mouse-selected) (define-key map 'button2 'undefined) (define-key map "\C-m" 'list-mode-item-keyboard-selected) ;; ;; The following calls to `substitute-key-definition' losed because ;; they were based on an incorrect assumption that `forward-char' and ;; `backward-char' are bound to keys in the global map. This might not ;; be the case if a user binds motion keys to different functions, ;; and was not actually the case since 20.5 beta 28 or around. ;; ;; (substitute-key-definition 'forward-char 'next-list-mode-item map ;; global-map) ;; (substitute-key-definition 'backward-char 'previous-list-mode-item map ;; global-map) ;; ;; We bind standard keys to motion commands instead. ;; (dolist (key '(kp-right right (control ?f))) (define-key map key 'next-list-mode-item)) (dolist (key '(kp-left left (control ?b))) (define-key map key 'previous-list-mode-item)))) ;; #### We make list-mode-hook, as well as completion-setup-hook and ;; minibuffer-setup-hook, permanent-local so that it's possible to create ;; buffers in these modes and then set up some buffer-specific ;; customizations without resorting to awful kludges. (The problem here ;; is that when you switch a buffer into a mode, reset-buffer is usually ;; called, which destroys all buffer-local settings that you carefully ;; tried to set up when you created the buffer. Therefore, the only way ;; to set these variables is to use the setup hooks -- but if they are ;; not declared permanent local, then any local hook functions that you ;; put on them (which is exactly what you want to do) also get removed, ;; so you would have to resort to putting a global hook function on the ;; setup hook, and then making sure it gets removed later. I actually ;; added some support for doing this with one-shot hooks, but this is ;; clearly not the correct way to do things, and it fails in some cases, ;; particularly when the buffer gets put into the mode more than once, ;; which typically happens with completion buffers, for example.) In ;; fact, all setup hooks should be made permanent local, but I didn't ;; feel like making a global change like this quite yet. The proper way ;; to do it would be to declare new def-style forms, such as defhook and ;; define-local-setup-hook, which are used to initialize hooks in place ;; of the current generic defvars. --ben (put 'list-mode-hook 'permanent-local t) (defvar list-mode-hook nil "Normal hook run when entering List mode.") (defun list-mode () "Major mode for buffer containing lists of items." (interactive) (kill-all-local-variables) (use-local-map list-mode-map) (setq mode-name "List") (setq major-mode 'list-mode) (add-local-hook 'post-command-hook 'set-list-mode-extent) (add-local-hook 'pre-command-hook 'list-mode-extent-pre-hook) (set (make-local-variable 'next-line-add-newlines) nil) (setq list-mode-extent nil) ;; It is visually disconcerting to have the text cursor disappear within list ;; buffers, especially when moving from window to window, so leave it ;; visible. -- Bob Weiner, 06/20/1999 ; (set-specifier text-cursor-visible-p nil (current-buffer)) (setq buffer-read-only t) (goto-char (point-min)) (run-hooks 'list-mode-hook)) ;; List mode is suitable only for specially formatted data. (put 'list-mode 'mode-class 'special) (defvar list-mode-extent-old-point nil "The value of point when pre-command-hook is called. Used to determine the direction of motion.") (make-variable-buffer-local 'list-mode-extent-old-point) (defun list-mode-extent-pre-hook () (setq list-mode-extent-old-point (point)) ;(setq atomic-extent-goto-char-p nil) ) (defun set-list-mode-extent () "Move to the closest list item and set up the extent for it. This is called from `post-command-hook'." (cond ((get-char-property (point) 'list-mode-item)) ((and (> (point) (point-min)) (get-char-property (1- (point)) 'list-mode-item)) (goto-char (1- (point)))) (t (let ((pos (point)) dirflag) ;this fucks things up more than it helps. ;atomic-extent-goto-char-p as currently defined is all broken, ;since it will be triggered if the command *ever* runs goto-char! ;(if atomic-extent-goto-char-p ; (setq dirflag 1) (if (and list-mode-extent-old-point (> pos list-mode-extent-old-point)) (setq dirflag 1) (setq dirflag -1)) (next-list-mode-item dirflag) (or (get-char-property (point) 'list-mode-item) (next-list-mode-item (- dirflag)))))) (or (and list-mode-extent (eq (current-buffer) (extent-object list-mode-extent))) (progn (setq list-mode-extent (make-extent nil nil (current-buffer))) (set-extent-face list-mode-extent 'list-mode-item-selected))) (let ((ex (extent-at (point) nil 'list-mode-item nil 'at))) (if ex (progn (set-extent-endpoints list-mode-extent (extent-start-position ex) (extent-end-position ex)) (auto-show-make-region-visible (extent-start-position ex) (extent-end-position ex))) (detach-extent list-mode-extent)))) (defun previous-list-mode-item (n) "Move to the previous item in list-mode." (interactive "p") (next-list-mode-item (- n))) (defun next-list-mode-item (n) "Move to the next item in list-mode. With prefix argument N, move N items (negative N means move backward)." (interactive "p") (while (and (> n 0) (not (eobp))) (let ((extent (extent-at (point) (current-buffer) 'list-mode-item)) (end (point-max))) ;; If in a completion, move to the end of it. (if extent (goto-char (extent-end-position extent))) ;; Move to start of next one. (or (extent-at (point) (current-buffer) 'list-mode-item) (goto-char (next-single-char-property-change (point) 'list-mode-item nil end)))) (setq n (1- n))) (while (and (< n 0) (not (bobp))) (let ((extent (extent-at (point) (current-buffer) 'list-mode-item)) (end (point-min))) ;; If in a completion, move to the start of it. (if extent (goto-char (extent-start-position extent))) ;; Move to the start of that one. (if (setq extent (extent-at (point) (current-buffer) 'list-mode-item nil 'before)) (goto-char (extent-start-position extent)) (goto-char (previous-single-char-property-change (point) 'list-mode-item nil end)) (if (setq extent (extent-at (point) (current-buffer) 'list-mode-item nil 'before)) (goto-char (extent-start-position extent))))) (setq n (1+ n)))) (defun list-mode-item-selected-1 (extent event) (let ((func (extent-property extent 'list-mode-item-activate-callback)) (user-data (extent-property extent 'list-mode-item-user-data))) (if func (funcall func event extent user-data)))) ;; we could make these two be just one function, but we want to be ;; able to refer to them in DOC strings. (defun list-mode-item-keyboard-selected () (interactive) (list-mode-item-selected-1 (extent-at (point) (current-buffer) 'list-mode-item nil 'at) nil)) (defun list-mode-item-mouse-selected (event) (interactive "e") ;; Sometimes event-closest-point returns nil. ;; So beep instead of bombing. (let ((point (event-closest-point event))) (if point (list-mode-item-selected-1 (extent-at point (event-buffer event) 'list-mode-item nil 'at) event) (ding)))) (defun add-list-mode-item (start end &optional buffer activate-callback user-data) "Add a new list item in list-mode, from START to END in BUFFER. BUFFER defaults to the current buffer. This works by creating an extent for the span of text in question. If ACTIVATE-CALLBACK is non-nil, it should be a function of three arguments (EVENT EXTENT USER-DATA) that will be called when button2 is pressed on the extent. USER-DATA comes from the optional USER-DATA argument." (let ((extent (make-extent start end buffer))) (set-extent-property extent 'list-mode-item t) (set-extent-property extent 'start-open t) (if activate-callback (progn (set-extent-property extent 'mouse-face 'highlight) (set-extent-property extent 'list-mode-item-activate-callback activate-callback) (set-extent-property extent 'list-mode-item-user-data user-data))) extent)) ;; Define the major mode for lists of completions. (defvar completion-highlight-first-word-only nil "*Completion will only highlight the first blank delimited word if t. If the variable in not t or nil, the string is taken as a regexp to match for end of highlight") ;; see comment at list-mode-hook. (put 'completion-setup-hook 'permanent-local t) (defvar completion-setup-hook nil "Normal hook run at the end of setting up the text of a completion buffer. When run, the completion buffer is the current buffer.") ; Unnecessary FSFmacs crock. We frob the extents directly in ; display-completion-list, so no "heuristics" like this are necessary. ;(defvar completion-fixup-function nil ; "A function to customize how completions are identified in completion lists. ;`completion-setup-function' calls this function with no arguments ;each time it has found what it thinks is one completion. ;Point is at the end of the completion in the completion list buffer. ;If this function moves point, it can alter the end of that completion.") (defvar completion-default-help-string '(concat (if (device-on-window-system-p) (substitute-command-keys "Click \\<list-mode-map>\\[list-mode-item-mouse-selected] on a completion to select it.\n") "") (substitute-command-keys "Type \\<minibuffer-local-completion-map>\\[advertised-switch-to-completions] or \\[switch-to-completions] to move to this buffer, for keyboard selection.\n\n")) "Form the evaluate to get a help string for completion lists. This string is inserted at the beginning of the buffer. See `display-completion-list'.") (defun* display-completion-list (completions &key user-data reference-buffer (activate-callback 'default-choose-completion) (help-string completion-default-help-string) (completion-string "Possible completions are:") window-width window-height) "Display the list of completions, COMPLETIONS, using `standard-output'. Each element may be just a symbol or string or may be a list of two strings to be printed as if concatenated. Frob a mousable extent onto each completion. This extent has properties 'mouse-face (so it highlights when the mouse passes over it) and 'list-mode-item (so it can be located). Keywords: :activate-callback (default is `default-choose-completion') See `add-list-mode-item'. :user-data Value passed to activation callback. :window-width If non-nil, width to use in displaying the list, instead of the actual window's width. :window-height If non-nil, use no more than this many lines, and extend line width as necessary. :help-string (default is the value of `completion-default-help-string') Form to evaluate to get a string to insert at the beginning of the completion list buffer. This is evaluated when that buffer is the current buffer and after it has been put into completion-list-mode. :reference-buffer (default is the current buffer) This specifies the value of `completion-reference-buffer' in the completion buffer. This specifies the buffer (normally a minibuffer) that `default-choose-completion' will insert the completion into. At the end, run the normal hook `completion-setup-hook'. It can find the completion buffer in `standard-output'. If `completion-highlight-first-word-only' is non-nil, then only the start of the string is highlighted." ;; #### I18N3 should set standard-output to be (temporarily) ;; output-translating. (let ((old-buffer (current-buffer)) (bufferp (bufferp standard-output))) (if bufferp (set-buffer standard-output)) (if (null completions) (princ (gettext "There are no possible completions of what you have typed.")) (let ((win-width (or window-width (if bufferp ;; We have to use last-nonminibuf-frame here ;; and not selected-frame because if a ;; minibuffer-only frame is being used it will ;; be the selected-frame at the point this is ;; run. We keep the selected-frame call around ;; just in case. (window-width (get-lru-window (last-nonminibuf-frame))) 80)))) (let ((count 0) (max-width 0) old-max-width) ;; Find longest completion (let ((tail completions)) (while tail (let* ((elt (car tail)) (len (cond ((stringp elt) (length elt)) ((and (consp elt) (stringp (car elt)) (stringp (car (cdr elt)))) (+ (length (car elt)) (length (car (cdr elt))))) (t (signal 'wrong-type-argument (list 'stringp elt)))))) (if (> len max-width) (setq max-width len)) (setq count (1+ count) tail (cdr tail))))) (setq max-width (+ 2 max-width)) ; at least two chars between cols (setq old-max-width max-width) (let ((rows (let ((cols (min (/ win-width max-width) count))) (if (<= cols 1) count (progn ;; re-space the columns (setq max-width (/ win-width cols)) (if (/= (% count cols) 0) ; want ceiling... (1+ (/ count cols)) (/ count cols))))))) (when (and window-height (> rows window-height)) (setq max-width old-max-width) (setq rows window-height)) (when (and (stringp completion-string) (> (length completion-string) 0)) (princ (gettext completion-string)) (terpri)) (let ((tail completions) (r 0) (regexp-string (if (eq t completion-highlight-first-word-only) "[ \t]" completion-highlight-first-word-only))) (while (< r rows) (and (> r 0) (terpri)) (let ((indent 0) (column 0) (tail2 tail)) (while tail2 (let ((elt (car tail2))) (if (/= indent 0) (if bufferp (indent-to indent 2) (while (progn (write-char ?\ ) (setq column (1+ column)) (< column indent))))) (setq indent (+ indent max-width)) (let ((start (point)) end) ;; Frob some mousable extents in there too! (if (consp elt) (progn (princ (car elt)) (princ (car (cdr elt))) (or bufferp (setq column (+ column (length (car elt)) (length (car (cdr elt))))))) (progn (princ elt) (or bufferp (setq column (+ column (length elt)))))) (add-list-mode-item start (progn (setq end (point)) (or (and completion-highlight-first-word-only (goto-char start) (re-search-forward regexp-string end t) (match-beginning 0)) end)) nil activate-callback user-data) (goto-char end))) (setq tail2 (nthcdr rows tail2))) (setq tail (cdr tail) r (1+ r))))))))) (if bufferp (set-buffer old-buffer))) (save-excursion (let ((mainbuf (or reference-buffer (current-buffer)))) (set-buffer standard-output) (completion-list-mode) (make-local-variable 'completion-reference-buffer) (setq completion-reference-buffer mainbuf) ;;; The value 0 is right in most cases, but not for file name completion. ;;; so this has to be turned off. ;;; (setq completion-base-size 0) (goto-char (point-min)) (let ((buffer-read-only nil)) (insert (eval help-string))) ;; unnecessary FSFmacs crock ;;(forward-line 1) ;;(while (re-search-forward "[^ \t\n]+\\( [^ \t\n]+\\)*" nil t) ;; (let ((beg (match-beginning 0)) ;; (end (point))) ;; (if completion-fixup-function ;; (funcall completion-fixup-function)) ;; (put-text-property beg (point) 'mouse-face 'highlight) ;; (put-text-property beg (point) 'list-mode-item t) ;; (goto-char end))))) )) (save-excursion (set-buffer standard-output) (run-hooks 'completion-setup-hook))) (defvar completion-display-completion-list-function 'display-completion-list "Function to set up the list of completions in the completion buffer. The function is called with one argument, the sorted list of completions. Particular minibuffer interface functions (e.g. `read-file-name') may want to change this. To do that, set a local value for this variable in the minibuffer; that ensures that other minibuffer invocations will not be affected.") (defun minibuffer-completion-help () "Display a list of possible completions of the current minibuffer contents. The list of completions is determined by calling `all-completions', passing it the current minibuffer contents, the value of `minibuffer-completion-table', and the value of `minibuffer-completion-predicate'. The list is displayed by calling the value of `completion-display-completion-list-function' on the sorted list of completions, with the standard output set to the completion buffer." (interactive) (message "Making completion list...") (let ((completions (all-completions (buffer-string) minibuffer-completion-table minibuffer-completion-predicate))) (message nil) (if (null completions) (progn (ding nil 'no-completion) (temp-minibuffer-message " [No completions]")) (with-output-to-temp-buffer "*Completions*" (funcall completion-display-completion-list-function (sort completions #'string-lessp)))))) (define-derived-mode completion-list-mode list-mode "Completion List" "Major mode for buffers showing lists of possible completions. \\{completion-list-mode-map}" (make-local-variable 'completion-base-size) (setq completion-base-size nil)) (let ((map completion-list-mode-map)) (define-key map 'button2up 'mouse-choose-completion) (define-key map 'button2 'undefined) (define-key map "\C-m" 'choose-completion) (define-key map "\e\e\e" 'delete-completion-window) (define-key map "\C-g" 'minibuffer-keyboard-quit) (define-key map "q" 'completion-list-mode-quit) (define-key map " " 'completion-switch-to-minibuffer) ;; [Tab] used to switch to the minibuffer but since [space] does that and ;; since most applications in the world use [Tab] to select the next item ;; in a list, do that in the *Completions* buffer too. -- Bob Weiner, ;; BeOpen.com, 06/23/1999. (define-key map "\t" 'next-list-mode-item)) (defvar completion-reference-buffer nil "Record the buffer that was current when the completion list was requested. This is a local variable in the completion list buffer. Initial value is nil to avoid some compiler warnings.") (defvar completion-base-size nil "Number of chars at beginning of minibuffer not involved in completion. This is a local variable in the completion list buffer but it talks about the buffer in `completion-reference-buffer'. If this is nil, it means to compare text to determine which part of the tail end of the buffer's text is involved in completion.") ;; These names are referenced in the doc string for `completion-list-mode'. (defalias 'choose-completion 'list-mode-item-keyboard-selected) (defalias 'mouse-choose-completion 'list-mode-item-mouse-selected) (defun delete-completion-window () "Delete the completion list window. Go to the window from which completion was requested." (interactive) (let ((buf completion-reference-buffer)) (delete-window (selected-window)) (if (get-buffer-window buf) (select-window (get-buffer-window buf))))) (defun completion-switch-to-minibuffer () "Move from a completions buffer to the active minibuffer window." (interactive) (select-window (minibuffer-window))) (defun completion-list-mode-quit () "Abort any recursive edit and bury the completions buffer." (interactive) (condition-case () (abort-recursive-edit) (error nil)) ;; If there was no recursive edit to abort, simply bury the completions ;; list buffer. (if (eq major-mode 'completion-list-mode) (bury-buffer))) (defun completion-do-in-minibuffer () (interactive "_") (save-excursion (set-buffer (window-buffer (minibuffer-window))) (call-interactively (key-binding (this-command-keys))))) (defun default-choose-completion (event extent buffer) "Click on an alternative in the `*Completions*' buffer to choose it." (and (button-event-p event) ;; Give temporary modes such as isearch a chance to turn off. (run-hooks 'mouse-leave-buffer-hook)) (or buffer (setq buffer (symbol-value-in-buffer 'completion-reference-buffer (or (and (button-event-p event) (event-buffer event)) (current-buffer))))) (save-selected-window (and (button-event-p event) (select-window (event-window event))) (if (and (one-window-p t 'selected-frame) (window-dedicated-p (selected-window))) ;; This is a special buffer's frame (iconify-frame (selected-frame)) (or (window-dedicated-p (selected-window)) (bury-buffer)))) (choose-completion-string (extent-string extent) buffer completion-base-size)) ;; Delete the longest partial match for STRING ;; that can be found before POINT. (defun choose-completion-delete-max-match (string) (let ((len (min (length string) (- (point) (point-min))))) (goto-char (- (point) (length string))) (if completion-ignore-case (setq string (downcase string))) (while (and (> len 0) (let ((tail (buffer-substring (point) (+ (point) len)))) (if completion-ignore-case (setq tail (downcase tail))) (not (string= tail (substring string 0 len))))) (setq len (1- len)) (forward-char 1)) (delete-char len))) ;; Switch to BUFFER and insert the completion choice CHOICE. ;; BASE-SIZE, if non-nil, says how many characters of BUFFER's text ;; to keep. If it is nil, use choose-completion-delete-max-match instead. (defun choose-completion-string (choice &optional buffer base-size) (let ((buffer (or buffer completion-reference-buffer))) ;; If BUFFER is a minibuffer, barf unless it's the currently ;; active minibuffer. (if (and (string-match "\\` \\*Minibuf-[0-9]+\\*\\'" (buffer-name buffer)) (or (not (active-minibuffer-window)) (not (equal buffer (window-buffer (active-minibuffer-window)))))) (error "Minibuffer is not active for completion") ;; Insert the completion into the buffer where completion was requested. (set-buffer buffer) (if base-size (delete-region (+ base-size (point-min)) (point)) (choose-completion-delete-max-match choice)) (insert choice) (remove-text-properties (- (point) (length choice)) (point) '(highlight nil)) ;; Update point in the window that BUFFER is showing in. (let ((window (get-buffer-window buffer t))) (set-window-point window (point))) ;; If completing for the minibuffer, exit it with this choice. (and (equal buffer (window-buffer (minibuffer-window))) minibuffer-completion-table (exit-minibuffer))))) (define-key minibuffer-local-completion-map [prior] 'switch-to-completions) (define-key minibuffer-local-must-match-map [prior] 'switch-to-completions) (define-key minibuffer-local-completion-map "\M-v" 'advertised-switch-to-completions) (define-key minibuffer-local-must-match-map "\M-v" 'advertised-switch-to-completions) (defalias 'advertised-switch-to-completions 'switch-to-completions) (defun switch-to-completions () "Select the completion list window." (interactive) ;; Make sure we have a completions window. (or (get-buffer-window "*Completions*") (minibuffer-completion-help)) (if (not (get-buffer-window "*Completions*")) nil (select-window (get-buffer-window "*Completions*")) (goto-char (next-single-char-property-change (point-min) 'list-mode-item nil (point-max))))) ;;; list-mode.el ends here