Introduce fast path for the widely used marker operation.
[emacs.git] / lisp / minibuf-eldef.el
blob4387fc625c6563e3427430115d850f2649a0ff92
1 ;;; minibuf-eldef.el --- Only show defaults in prompts when applicable
2 ;;
3 ;; Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 ;;
5 ;; Author: Miles Bader <miles@gnu.org>
6 ;; Keywords: convenience
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 ;;; Commentary:
25 ;; Defines the mode `minibuffer-electric-default-mode'.
27 ;; When active, minibuffer prompts that show a default value only show
28 ;; the default when it's applicable -- that is, when hitting RET would
29 ;; yield the default value. If the user modifies the input such that
30 ;; hitting RET would enter a non-default value, the prompt is modified
31 ;; to remove the default indication (which is restored if the input is
32 ;; ever restore to the match the initial input).
34 ;;; Code:
36 (defvar minibuffer-default-in-prompt-regexps
37 '(("\\( (default\\>.*)\\):? \\'" . 1) ("\\( \\[.*\\]\\):? *\\'" . 1))
38 "A list of regexps matching the parts of minibuffer prompts showing defaults.
39 When `minibuffer-electric-default-mode' is active, these regexps are
40 used to identify the portions of prompts to elide.
42 Each entry is either a string, which should be a regexp matching the
43 default portion of the prompt, or a cons cell, who's car is a regexp
44 matching the default part of the prompt, and who's cdr indicates the
45 regexp subexpression that matched.")
48 ;;; Internal variables
50 ;; A list of minibuffers to which we've added a post-command-hook.
51 (defvar minibuf-eldef-frobbed-minibufs nil)
53 ;;; The following are all local variables in the minibuffer
55 ;; Input pre-inserted into the minibuffer before the user can edit it.
56 (defvar minibuf-eldef-initial-input)
57 (make-variable-buffer-local 'minibuf-eldef-initial-input)
58 ;; and the length of the buffer with it inserted.
59 (defvar minibuf-eldef-initial-buffer-length)
60 (make-variable-buffer-local 'minibuf-eldef-initial-buffer-length)
62 ;; True if the current minibuffer prompt contains the default spec.
63 (defvar minibuf-eldef-showing-default-in-prompt)
64 (make-variable-buffer-local 'minibuf-eldef-showing-default-in-prompt)
66 ;; An overlay covering the default portion of the prompt
67 (defvar minibuf-eldef-overlay)
68 (make-variable-buffer-local 'minibuf-eldef-overlay)
71 ;;; Hook functions
73 ;; This function goes on minibuffer-setup-hook
74 (defun minibuf-eldef-setup-minibuffer ()
75 "Set up a minibuffer for `minibuffer-electric-default-mode'.
76 The prompt and initial input should already have been inserted."
77 (let ((regexps minibuffer-default-in-prompt-regexps)
78 (match nil)
79 (inhibit-point-motion-hooks t))
80 (save-excursion
81 (save-restriction
82 ;; Narrow to only the prompt
83 (goto-char (point-min))
84 (narrow-to-region (point) (minibuffer-prompt-end))
85 ;; See the prompt contains a default input indicator
86 (while regexps
87 (setq match (pop regexps))
88 (if (re-search-forward (if (stringp match) match (car match)) nil t)
89 (setq regexps nil)
90 (setq match nil)))))
91 (if (not match)
92 ;; Nope, so just make sure our post-command-hook isn't left around.
93 (remove-hook 'post-command-hook #'minibuf-eldef-update-minibuffer t)
94 ;; Yup; set things up so we can frob the prompt as the state of
95 ;; the input string changes.
96 (setq match (if (consp match) (cdr match) 0))
97 (setq minibuf-eldef-overlay
98 (make-overlay (match-beginning match) (match-end match)))
99 (setq minibuf-eldef-showing-default-in-prompt t)
100 (setq minibuf-eldef-initial-input
101 (minibuffer-contents-no-properties))
102 (setq minibuf-eldef-initial-buffer-length (point-max))
103 (add-to-list 'minibuf-eldef-frobbed-minibufs (current-buffer))
104 (add-hook 'post-command-hook #'minibuf-eldef-update-minibuffer nil t))))
106 ;; post-command-hook to swap prompts when necessary
107 (defun minibuf-eldef-update-minibuffer ()
108 "Update a minibuffer's prompt to include a default only when applicable.
109 This is intended to be used as a minibuffer post-command-hook for
110 `minibuffer-electric-default-mode'; the minibuffer should have already
111 been set up by `minibuf-eldef-setup-minibuffer'."
112 (unless (eq minibuf-eldef-showing-default-in-prompt
113 (and (= (point-max) minibuf-eldef-initial-buffer-length)
114 (string-equal (minibuffer-contents-no-properties)
115 minibuf-eldef-initial-input)))
116 ;; swap state
117 (setq minibuf-eldef-showing-default-in-prompt
118 (not minibuf-eldef-showing-default-in-prompt))
119 (cond (minibuf-eldef-showing-default-in-prompt
120 (overlay-put minibuf-eldef-overlay 'invisible nil)
121 (overlay-put minibuf-eldef-overlay 'intangible nil))
123 (overlay-put minibuf-eldef-overlay 'invisible t)
124 (overlay-put minibuf-eldef-overlay 'intangible t)))))
127 ;;; Note this definition must be at the end of the file, because
128 ;;; `define-minor-mode' actually calls the mode-function if the
129 ;;; associated variable is non-nil, which requires that all needed
130 ;;; functions be already defined. [This is arguably a bug in d-m-m]
131 ;;;###autoload
132 (define-minor-mode minibuffer-electric-default-mode
133 "Toggle Minibuffer Electric Default mode.
134 With a prefix argument ARG, enable Minibuffer Electric Default
135 mode if ARG is positive, and disable it otherwise. If called
136 from Lisp, enable the mode if ARG is omitted or nil.
138 Minibuffer Electric Default mode is a global minor mode. When
139 enabled, minibuffer prompts that show a default value only show
140 the default when it's applicable -- that is, when hitting RET
141 would yield the default value. If the user modifies the input
142 such that hitting RET would enter a non-default value, the prompt
143 is modified to remove the default indication."
144 :global t
145 :group 'minibuffer
146 (if minibuffer-electric-default-mode
147 ;; Enable the mode
148 (add-hook 'minibuffer-setup-hook 'minibuf-eldef-setup-minibuffer)
149 ;; Disable the mode
150 (remove-hook 'minibuffer-setup-hook 'minibuf-eldef-setup-minibuffer)
151 ;; Remove our entry from any post-command-hook variable's it's still in
152 (dolist (minibuf minibuf-eldef-frobbed-minibufs)
153 (with-current-buffer minibuf
154 (remove-hook 'post-command-hook #'minibuf-eldef-update-minibuffer t)))
155 (setq minibuf-eldef-frobbed-minibufs nil)))
158 (provide 'minibuf-eldef)
160 ;;; minibuf-eldef.el ends here