minibuf-eldef.el 6.6 KB

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