More tweaks of skeleton documentation wrt \n behavior at bol/eol.
[bpt/emacs.git] / lisp / minibuf-eldef.el
CommitLineData
a2e770db 1;;; minibuf-eldef.el --- Only show defaults in prompts when applicable -*- lexical-binding: t -*-
66d058c4 2;;
ba318903 3;; Copyright (C) 2000-2014 Free Software Foundation, Inc.
66d058c4
MB
4;;
5;; Author: Miles Bader <miles@gnu.org>
6;; Keywords: convenience
7
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
66d058c4 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
66d058c4
MB
14
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.
19
20;; You should have received a copy of the GNU General Public License
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
66d058c4
MB
22
23;;; Commentary:
24;;
25;; Defines the mode `minibuffer-electric-default-mode'.
26;;
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).
33
34;;; Code:
35
7d806bfe 36(defvar minibuffer-eldef-shorten-default)
a2e770db 37
7d806bfe 38(defun minibuffer-default--in-prompt-regexps ()
a2e770db
SM
39 `(("\\( (default\\(?: is\\)? \\(.*\\))\\):? \\'"
40 1 ,(if minibuffer-eldef-shorten-default " [\\2]"))
2f108463 41 ("([^(]+?\\(, default\\(?: is\\)? \\(.*\\)\\)):? \\'" 1)
7d806bfe
CY
42 ("\\( \\[.*\\]\\):? *\\'" 1)))
43
44(defcustom minibuffer-eldef-shorten-default nil
45 "If non-nil, shorten \"(default ...)\" to \"[...]\" in minibuffer prompts."
46 :set (lambda (symbol value)
47 (set-default symbol value)
48 (setq-default minibuffer-default-in-prompt-regexps
49 (minibuffer-default--in-prompt-regexps)))
50 :type 'boolean
51 :group 'minibuffer
52 :version "24.3")
53
54(defvar minibuffer-default-in-prompt-regexps
55 (minibuffer-default--in-prompt-regexps)
fb7ada5f 56 "A list of regexps matching the parts of minibuffer prompts showing defaults.
66d058c4
MB
57When `minibuffer-electric-default-mode' is active, these regexps are
58used to identify the portions of prompts to elide.
59
a2e770db
SM
60Each entry is of the form (REGEXP MATCH-NUM &optional REWRITE),
61where REGEXP should match the default part of the prompt,
62MATCH-NUM is the subgroup that matched the actual default indicator,
63and REWRITE, if present, is a string to pass to `replace-match' that
64should be displayed in its place.")
66d058c4
MB
65
66\f
67;;; Internal variables
68
69;; A list of minibuffers to which we've added a post-command-hook.
70(defvar minibuf-eldef-frobbed-minibufs nil)
f1180544 71
66d058c4
MB
72;;; The following are all local variables in the minibuffer
73
74;; Input pre-inserted into the minibuffer before the user can edit it.
75(defvar minibuf-eldef-initial-input)
76(make-variable-buffer-local 'minibuf-eldef-initial-input)
77;; and the length of the buffer with it inserted.
78(defvar minibuf-eldef-initial-buffer-length)
79(make-variable-buffer-local 'minibuf-eldef-initial-buffer-length)
80
81;; True if the current minibuffer prompt contains the default spec.
82(defvar minibuf-eldef-showing-default-in-prompt)
83(make-variable-buffer-local 'minibuf-eldef-showing-default-in-prompt)
84
85;; An overlay covering the default portion of the prompt
86(defvar minibuf-eldef-overlay)
87(make-variable-buffer-local 'minibuf-eldef-overlay)
88
89\f
90;;; Hook functions
91
92;; This function goes on minibuffer-setup-hook
93(defun minibuf-eldef-setup-minibuffer ()
94 "Set up a minibuffer for `minibuffer-electric-default-mode'.
95The prompt and initial input should already have been inserted."
8bbb7c70 96 (let ((regexps minibuffer-default-in-prompt-regexps)
66d058c4
MB
97 (match nil)
98 (inhibit-point-motion-hooks t))
99 (save-excursion
100 (save-restriction
a2e770db 101 ;; Narrow to only the prompt.
66d058c4 102 (goto-char (point-min))
8bbb7c70 103 (narrow-to-region (point) (minibuffer-prompt-end))
a2e770db 104 ;; See if the prompt contains a default input indicator.
66d058c4
MB
105 (while regexps
106 (setq match (pop regexps))
a2e770db
SM
107 (cond
108 ((not (re-search-forward (if (stringp match) match (car match))
109 nil t))
110 ;; No match yet, try the next rule.
111 (setq match nil))
112 ((and (consp (cdr-safe match)) (nth 2 match))
113 ;; Matched a replacement rule.
114 (let* ((inhibit-read-only t)
115 (buffer-undo-list t)
116 (submatch (nth 1 match))
117 (replacement (nth 2 match))
118 (props (text-properties-at (match-beginning submatch))))
119 (replace-match replacement nil nil nil submatch)
120 (set-text-properties (match-beginning submatch)
121 (match-end submatch)
122 props)
123 ;; Replacement done, now keep trying with subsequent rules.
124 (setq match nil)
125 (goto-char (point-min))))
126 ;; Matched a non-replacement (i.e. electric hide) rule, no need to
127 ;; keep trying.
128 (t (setq regexps nil))))))
66d058c4 129 (if (not match)
a2e770db
SM
130 ;; No match for electric hiding, so just make sure our
131 ;; post-command-hook isn't left around.
66d058c4
MB
132 (remove-hook 'post-command-hook #'minibuf-eldef-update-minibuffer t)
133 ;; Yup; set things up so we can frob the prompt as the state of
134 ;; the input string changes.
135 (setq match (if (consp match) (cdr match) 0))
a2e770db 136 (setq match (if (consp match) (car match) match))
66d058c4
MB
137 (setq minibuf-eldef-overlay
138 (make-overlay (match-beginning match) (match-end match)))
139 (setq minibuf-eldef-showing-default-in-prompt t)
140 (setq minibuf-eldef-initial-input
8bbb7c70 141 (minibuffer-contents-no-properties))
66d058c4
MB
142 (setq minibuf-eldef-initial-buffer-length (point-max))
143 (add-to-list 'minibuf-eldef-frobbed-minibufs (current-buffer))
144 (add-hook 'post-command-hook #'minibuf-eldef-update-minibuffer nil t))))
145
146;; post-command-hook to swap prompts when necessary
147(defun minibuf-eldef-update-minibuffer ()
148 "Update a minibuffer's prompt to include a default only when applicable.
149This is intended to be used as a minibuffer post-command-hook for
150`minibuffer-electric-default-mode'; the minibuffer should have already
151been set up by `minibuf-eldef-setup-minibuffer'."
152 (unless (eq minibuf-eldef-showing-default-in-prompt
153 (and (= (point-max) minibuf-eldef-initial-buffer-length)
8bbb7c70 154 (string-equal (minibuffer-contents-no-properties)
66d058c4 155 minibuf-eldef-initial-input)))
4b5c89ee 156 ;; Swap state.
66d058c4
MB
157 (setq minibuf-eldef-showing-default-in-prompt
158 (not minibuf-eldef-showing-default-in-prompt))
4b5c89ee
SM
159 (overlay-put minibuf-eldef-overlay 'invisible
160 (not minibuf-eldef-showing-default-in-prompt))))
66d058c4
MB
161
162\f
66d058c4
MB
163;;;###autoload
164(define-minor-mode minibuffer-electric-default-mode
35cd0213 165 "Toggle Minibuffer Electric Default mode.
06e21633
CY
166With a prefix argument ARG, enable Minibuffer Electric Default
167mode if ARG is positive, and disable it otherwise. If called
168from Lisp, enable the mode if ARG is omitted or nil.
169
170Minibuffer Electric Default mode is a global minor mode. When
171enabled, minibuffer prompts that show a default value only show
172the default when it's applicable -- that is, when hitting RET
173would yield the default value. If the user modifies the input
174such that hitting RET would enter a non-default value, the prompt
175is modified to remove the default indication."
66d058c4
MB
176 :global t
177 :group 'minibuffer
178 (if minibuffer-electric-default-mode
179 ;; Enable the mode
180 (add-hook 'minibuffer-setup-hook 'minibuf-eldef-setup-minibuffer)
181 ;; Disable the mode
182 (remove-hook 'minibuffer-setup-hook 'minibuf-eldef-setup-minibuffer)
183 ;; Remove our entry from any post-command-hook variable's it's still in
184 (dolist (minibuf minibuf-eldef-frobbed-minibufs)
185 (with-current-buffer minibuf
186 (remove-hook 'post-command-hook #'minibuf-eldef-update-minibuffer t)))
187 (setq minibuf-eldef-frobbed-minibufs nil)))
188
189
190(provide 'minibuf-eldef)
191
192;;; minibuf-eldef.el ends here