From: Michael Albinus via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: "Kévin Le Gouguec" <kevin.legouguec@gmail.com>
Cc: 69237@debbugs.gnu.org
Subject: bug#69237: 30.0.50; Toggle password visibility
Date: Fri, 23 Feb 2024 16:43:17 +0100 [thread overview]
Message-ID: <8734tjrxt6.fsf@gmx.de> (raw)
In-Reply-To: <87h6i0xhbb.fsf@gmail.com> ("Kévin Le Gouguec"'s message of "Thu, 22 Feb 2024 22:30:48 +0000")
[-- Attachment #1: Type: text/plain, Size: 1693 bytes --]
Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:
Hi Kévin,
> No strong feelings re. keybindings; I've been using C-c C-c because I
> wanted something easy to mash, but TAB fits that criterion as well. Not
> sure we can leverage any well-established mnemonic from other keymaps;
> FWIW…
>
> * TAB could be familiar to some outline users, but they'll probably
> associate that binding to (un)folding, not necessarily hiding/revealing;
>
> * hideshow has multiple bindings for "toggle-hiding", so not sure we can
> count on any single one having enough "mindshare".
>
> (Not too worried about needing to input TAB verbatim - I tend to
> naturally reach for C-q TAB when I need to do that, since in most
> contexts Emacs has a useful command bound to TAB instead of
> self-insert-command)
There are not so many comments on the keybindings. I guess this is
because only few people read the bug-gnu-emacs ML. Let's install this on
master, and see who hollers :-)
> Other than the keybinding, the only other musing I have is regarding the
> indicator: wondering if icons.el could help trim some of the boilerplate
> down. In any case, it would give the user some degree of control over
> how the indicator is shown (via the icon-preference option) even if we
> don't provide 'emoji nor 'symbol variants.
>
> Not overly familiar with that library though - if that's something you
> think might be worth looking into, the define-icon forms in outline.el
> might help you assess how helpful the library would actually be.
That's a good idea. I've implemented it, see the reworked patch
appended. And now with documentation.
Best regards, Michael.
[-- Attachment #2: Type: text/x-patch, Size: 10454 bytes --]
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index aa27de72ba0..66dfdc93318 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -2562,6 +2562,14 @@ Reading a Password
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
diff --git a/etc/NEWS b/etc/NEWS
index 7b248c3fe78..4c9fe4bcb12 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -318,6 +318,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'.
+
\f
* Editing Changes in Emacs 30.1
diff --git a/etc/images/README b/etc/images/README
index a778d9ce6c3..77377d36b5a 100644
--- a/etc/images/README
+++ b/etc/images/README
@@ -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,5 @@ 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
diff --git a/etc/images/conceal.svg b/etc/images/conceal.svg
new file mode 100644
index 00000000000..172b73ed3d3
--- /dev/null
+++ b/etc/images/conceal.svg
@@ -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>
diff --git a/etc/images/reveal.svg b/etc/images/reveal.svg
new file mode 100644
index 00000000000..41ae3733a53
--- /dev/null
+++ b/etc/images/reveal.svg
@@ -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>
diff --git a/lisp/simple.el b/lisp/simple.el
index 9a33049f4ca..3003de0f06a 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10858,6 +10858,85 @@ visible-mode
(setq-local vis-mode-saved-buffer-invisibility-spec
buffer-invisibility-spec)
(setq buffer-invisibility-spec nil)))
+
+\f
+(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
+ ,(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" :height (0.8 . em))
+ (symbol "👁")
+ (text ""))
+ "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" :height (0.8 . em))
+ (symbol "⦵")
+ (text ""))
+ "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)))
+
\f
(defvar messages-buffer-mode-map
(let ((map (make-sparse-keymap)))
diff --git a/lisp/subr.el b/lisp/subr.el
index c317d558e24..555d0084545 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3375,14 +3375,23 @@ read-passwd-map
(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.
@@ -3420,18 +3429,20 @@ read-passwd
(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))))))))
next prev parent reply other threads:[~2024-02-23 15:43 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-16 13:33 bug#69237: 30.0.50; Toggle password visibility Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-18 19:00 ` Eli Zaretskii
2024-02-18 20:04 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-19 12:21 ` Eli Zaretskii
2024-02-19 15:54 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-19 16:48 ` Eli Zaretskii
2024-02-19 17:08 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-22 22:30 ` Kévin Le Gouguec
2024-02-23 15:43 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2024-02-23 16:56 ` Kévin Le Gouguec
2024-02-25 9:11 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-25 10:50 ` Kévin Le Gouguec
2024-02-25 11:25 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-25 13:34 ` Kévin Le Gouguec
2024-02-25 14:09 ` Eli Zaretskii
2024-02-25 14:38 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-25 14:42 ` Eli Zaretskii
2024-02-25 14:48 ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-25 15:27 ` Kévin Le Gouguec
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8734tjrxt6.fsf@gmx.de \
--to=bug-gnu-emacs@gnu.org \
--cc=69237@debbugs.gnu.org \
--cc=kevin.legouguec@gmail.com \
--cc=michael.albinus@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.