mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
'read-passwd' can toggle the visibility of passwords
* doc/lispref/minibuf.texi (Reading a Password): * etc/NEWS: 'read-passwd' can toggle the visibility of passwords. * etc/images/README: Mention the new images below. * etc/images/conceal.pbm: * etc/images/conceal.svg: * etc/images/reveal.pbm: * etc/images/reveal.svg: New images. * lisp/simple.el (read-passwd--mode-line-buffer) (read-passwd--mode-line-icon): New defvars. (read-passwd--toggle-visibility, read-passwd-mode): New defuns. * lisp/subr.el (read-passwd-map): Add 'TAB' binding. (read-passwd--hide-password): New defvar. (read-passwd--hide-password): Rename function from `read-password--hide-password'. Adapt callees. Implement both hiding and showing the password. (Bug#69237) (read-passwd): Call `read-passwd-mode'.
This commit is contained in:
parent
67ba629a91
commit
39e3fce0d5
9 changed files with 128 additions and 8 deletions
|
|
@ -2562,6 +2562,14 @@ times match.
|
|||
The optional argument @var{default} specifies the default password to
|
||||
return if the user enters empty input. If @var{default} is @code{nil},
|
||||
then @code{read-passwd} returns the null string in that case.
|
||||
|
||||
This function uses @code{read-passwd-mode}, a minor mode. It binds two
|
||||
keys in the minbuffer: @kbd{C-u} (@code{delete-minibuffer-contents})
|
||||
deletes the password, and @kbd{TAB}
|
||||
(@code{read-passwd--toggle-visibility}) toggles the visibility of the
|
||||
password. There is also an additional icon in the mode-line. Clicking
|
||||
on this icon with @key{mouse-1} toggles the visibility of the password
|
||||
as well.
|
||||
@end defun
|
||||
|
||||
@node Minibuffer Commands
|
||||
|
|
|
|||
11
etc/NEWS
11
etc/NEWS
|
|
@ -322,6 +322,12 @@ Previously, it was set to t but this broke remote file name detection.
|
|||
** Multi-character key echo now ends with a suggestion to use Help.
|
||||
Customize 'echo-keystrokes-help' to nil to prevent that.
|
||||
|
||||
+++
|
||||
** 'read-passwd' can toggle the visibility of passwords.
|
||||
Use 'TAB' in the minibuffer to show or hide the password. Likewise,
|
||||
there is an icon on the mode-line, which toggles the visibility of the
|
||||
password when clicking with 'mouse-1'.
|
||||
|
||||
|
||||
* Editing Changes in Emacs 30.1
|
||||
|
||||
|
|
@ -1939,7 +1945,8 @@ Example:
|
|||
"Uses c:\remote\dir\files and the key \C-x."
|
||||
...)
|
||||
|
||||
where the doc string contains four control characters CR, DEL, FF and ^X.
|
||||
where the docstring contains four control characters 'CR', 'DEL', 'FF'
|
||||
and 'C-x'.
|
||||
|
||||
The warning name is 'docstrings-control-chars'.
|
||||
|
||||
|
|
@ -2025,7 +2032,7 @@ automatically, which means that the size parameter to 'obarray-make' can
|
|||
safely be omitted. That is, they do not become slower as they fill up.
|
||||
|
||||
The old vector representation is still accepted by functions operating
|
||||
on obarrays, but 'obarrayp' only returns 't' for obarray objects.
|
||||
on obarrays, but 'obarrayp' only returns t for obarray objects.
|
||||
'type-of' now returns 'obarray' for obarray objects.
|
||||
|
||||
Old code which (incorrectly) created "obarrays" as Lisp vectors filled
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ For more information see the adwaita-icon-theme repository at:
|
|||
|
||||
https://gitlab.gnome.org/GNOME/adwaita-icon-theme
|
||||
|
||||
Emacs images and their source in the Adwaita/scalable directory:
|
||||
Emacs images and their source in the Adwaita/symbolic directory:
|
||||
|
||||
checked.svg ui/checkbox-checked-symbolic.svg
|
||||
unchecked.svg ui/checkbox-symbolic.svg
|
||||
|
|
@ -137,3 +137,8 @@ Emacs images and their source in the Adwaita/scalable directory:
|
|||
left.svg ui/pan-start-symbolic.svg
|
||||
right.svg ui/pan-end-symbolic.svg
|
||||
up.svg ui/pan-up-symbolic.svg
|
||||
conceal.svg actions/view-conceal-symbolic.svg
|
||||
reveal.svg actions/view-reveal-symbolic.svg
|
||||
|
||||
conceal.pbm and reveal.pbm are generated from the respective *.svg
|
||||
files, using the ImageMagick converter tool.
|
||||
|
|
|
|||
BIN
etc/images/conceal.pbm
Normal file
BIN
etc/images/conceal.pbm
Normal file
Binary file not shown.
4
etc/images/conceal.svg
Normal file
4
etc/images/conceal.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 1.53125 0.46875 l -1.0625 1.0625 l 14 14 l 1.0625 -1.0625 l -2.382812 -2.382812 c 1.265624 -1.0625 2.171874 -2.496094 2.589843 -4.097657 c -0.914062 -3.523437 -4.097656 -5.984375 -7.738281 -5.988281 c -1.367188 0.011719 -2.707031 0.371094 -3.894531 1.042969 z m 6.46875 3.53125 c 2.210938 0 4 1.789062 4 4 c -0.003906 0.800781 -0.246094 1.578125 -0.699219 2.238281 l -1.46875 -1.46875 c 0.105469 -0.242187 0.164063 -0.503906 0.167969 -0.769531 c 0 -1.105469 -0.894531 -2 -2 -2 c -0.265625 0.003906 -0.527344 0.0625 -0.769531 0.167969 l -1.46875 -1.46875 c 0.660156 -0.453125 1.4375 -0.695313 2.238281 -0.699219 z m -6.144531 0.917969 c -0.753907 0.898437 -1.296875 1.957031 -1.59375 3.09375 c 0.914062 3.523437 4.097656 5.984375 7.738281 5.988281 c 0.855469 -0.007812 1.703125 -0.152344 2.511719 -0.425781 l -1.667969 -1.667969 c -0.277344 0.058594 -0.5625 0.089844 -0.84375 0.09375 c -2.210938 0 -4 -1.789062 -4 -4 c 0.003906 -0.28125 0.035156 -0.566406 0.09375 -0.84375 z m 0 0" fill="#2e3436"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
etc/images/reveal.pbm
Normal file
BIN
etc/images/reveal.pbm
Normal file
Binary file not shown.
4
etc/images/reveal.svg
Normal file
4
etc/images/reveal.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 8 2 c -3.648438 0.003906 -6.832031 2.476562 -7.738281 6.007812 c 0.914062 3.527344 4.097656 5.988282 7.738281 5.992188 c 3.648438 -0.003906 6.832031 -2.476562 7.738281 -6.011719 c -0.914062 -3.523437 -4.097656 -5.984375 -7.738281 -5.988281 z m 0 2 c 2.210938 0 4 1.789062 4 4 s -1.789062 4 -4 4 s -4 -1.789062 -4 -4 s 1.789062 -4 4 -4 z m 0 2 c -1.105469 0 -2 0.894531 -2 2 s 0.894531 2 2 2 s 2 -0.894531 2 -2 s -0.894531 -2 -2 -2 z m 0 0" fill="#2e3436"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 606 B |
|
|
@ -10858,6 +10858,87 @@ and setting it to nil."
|
|||
(setq-local vis-mode-saved-buffer-invisibility-spec
|
||||
buffer-invisibility-spec)
|
||||
(setq buffer-invisibility-spec nil)))
|
||||
|
||||
|
||||
(defvar read-passwd--mode-line-buffer nil
|
||||
"Buffer to modify `mode-line-format' for showing/hiding passwords.")
|
||||
|
||||
(defvar read-passwd--mode-line-icon nil
|
||||
"Propertized mode line icon for showing/hiding passwords.")
|
||||
|
||||
(defun read-passwd--toggle-visibility ()
|
||||
"Toggle minibuffer contents visibility.
|
||||
Adapt also mode line."
|
||||
(interactive)
|
||||
(setq read-passwd--hide-password (not read-passwd--hide-password))
|
||||
(with-current-buffer read-passwd--mode-line-buffer
|
||||
(setq read-passwd--mode-line-icon
|
||||
`(:propertize
|
||||
,(if icon-preference
|
||||
(icon-string
|
||||
(if read-passwd--hide-password
|
||||
'read-passwd--show-password-icon
|
||||
'read-passwd--hide-password-icon))
|
||||
"")
|
||||
mouse-face mode-line-highlight
|
||||
local-map
|
||||
(keymap
|
||||
(mode-line keymap (mouse-1 . read-passwd--toggle-visibility)))))
|
||||
(force-mode-line-update))
|
||||
(read-passwd--hide-password))
|
||||
|
||||
(define-minor-mode read-passwd-mode
|
||||
"Toggle visibility of password in minibuffer."
|
||||
:group 'mode-line
|
||||
:group 'minibuffer
|
||||
:keymap read-passwd-map
|
||||
:version "30.1"
|
||||
|
||||
(require 'icons)
|
||||
;; It would be preferable to use "👁" ("\N{EYE}"). However, there is
|
||||
;; no corresponding Unicode char with a slash. So we use symbols as
|
||||
;; fallback only, with "⦵" ("\N{CIRCLE WITH HORIZONTAL BAR}") for
|
||||
;; hiding the password.
|
||||
(define-icon read-passwd--show-password-icon nil
|
||||
'((image "reveal.svg" "reveal.pbm" :height (0.8 . em))
|
||||
(symbol "👁")
|
||||
(text "o"))
|
||||
"Mode line icon to show a hidden password."
|
||||
:group mode-line-faces
|
||||
:version "30.1"
|
||||
:help-echo "mouse-1: Toggle password visibility")
|
||||
(define-icon read-passwd--hide-password-icon nil
|
||||
'((image "conceal.svg" "conceal.pbm" :height (0.8 . em))
|
||||
(symbol "⦵")
|
||||
(text "x"))
|
||||
"Mode line icon to hide a visible password."
|
||||
:group mode-line-faces
|
||||
:version "30.1"
|
||||
:help-echo "mouse-1: Toggle password visibility")
|
||||
|
||||
(setq read-passwd--hide-password nil
|
||||
;; Stolen from `eldoc-minibuffer-message'.
|
||||
read-passwd--mode-line-buffer
|
||||
(window-buffer
|
||||
(or (window-in-direction 'above (minibuffer-window))
|
||||
(minibuffer-selected-window)
|
||||
(get-largest-window))))
|
||||
|
||||
(if read-passwd-mode
|
||||
(with-current-buffer read-passwd--mode-line-buffer
|
||||
;; Add `read-passwd--mode-line-icon'.
|
||||
(when (listp mode-line-format)
|
||||
(setq mode-line-format
|
||||
(cons '(:eval read-passwd--mode-line-icon)
|
||||
mode-line-format))))
|
||||
(with-current-buffer read-passwd--mode-line-buffer
|
||||
;; Remove `read-passwd--mode-line-icon'.
|
||||
(when (listp mode-line-format)
|
||||
(setq mode-line-format (cdr mode-line-format)))))
|
||||
|
||||
(when read-passwd-mode
|
||||
(read-passwd--toggle-visibility)))
|
||||
|
||||
|
||||
(defvar messages-buffer-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
|
|
|
|||
21
lisp/subr.el
21
lisp/subr.el
|
|
@ -3378,14 +3378,23 @@ with Emacs. Do not call it directly in your own packages."
|
|||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map minibuffer-local-map)
|
||||
(define-key map "\C-u" #'delete-minibuffer-contents) ;bug#12570
|
||||
(define-key map "\t" #'read-passwd--toggle-visibility)
|
||||
map)
|
||||
"Keymap used while reading passwords.")
|
||||
|
||||
(defun read-password--hide-password ()
|
||||
(defvar read-passwd--hide-password t)
|
||||
|
||||
(defun read-passwd--hide-password ()
|
||||
"Make password in minibuffer hidden or visible."
|
||||
(let ((beg (minibuffer-prompt-end)))
|
||||
(dotimes (i (1+ (- (buffer-size) beg)))
|
||||
(put-text-property (+ i beg) (+ 1 i beg)
|
||||
'display (string (or read-hide-char ?*))))))
|
||||
(if read-passwd--hide-password
|
||||
(put-text-property
|
||||
(+ i beg) (+ 1 i beg) 'display (string (or read-hide-char ?*)))
|
||||
(remove-list-of-text-properties (+ i beg) (+ 1 i beg) '(display)))
|
||||
(put-text-property
|
||||
(+ i beg) (+ 1 i beg)
|
||||
'help-echo "C-u: Clear password\nTAB: Toggle password visibility"))))
|
||||
|
||||
(defun read-passwd (prompt &optional confirm default)
|
||||
"Read a password, prompting with PROMPT, and return it.
|
||||
|
|
@ -3423,18 +3432,20 @@ by doing (clear-string STRING)."
|
|||
(setq-local inhibit-modification-hooks nil) ;bug#15501.
|
||||
(setq-local show-paren-mode nil) ;bug#16091.
|
||||
(setq-local inhibit--record-char t)
|
||||
(add-hook 'post-command-hook #'read-password--hide-password nil t))
|
||||
(read-passwd-mode 1)
|
||||
(add-hook 'post-command-hook #'read-passwd--hide-password nil t))
|
||||
(unwind-protect
|
||||
(let ((enable-recursive-minibuffers t)
|
||||
(read-hide-char (or read-hide-char ?*)))
|
||||
(read-string prompt nil t default)) ; t = "no history"
|
||||
(when (buffer-live-p minibuf)
|
||||
(with-current-buffer minibuf
|
||||
(read-passwd-mode -1)
|
||||
;; Not sure why but it seems that there might be cases where the
|
||||
;; minibuffer is not always properly reset later on, so undo
|
||||
;; whatever we've done here (bug#11392).
|
||||
(remove-hook 'after-change-functions
|
||||
#'read-password--hide-password 'local)
|
||||
#'read-passwd--hide-password 'local)
|
||||
(kill-local-variable 'post-self-insert-hook)
|
||||
;; And of course, don't keep the sensitive data around.
|
||||
(erase-buffer))))))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue