From: "Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Lars Ingebrigtsen <larsi@gnus.org>
Cc: 45412@debbugs.gnu.org, "積丹尼 Dan Jacobson" <jidanni@jidanni.org>,
"Juri Linkov" <juri@linkov.net>
Subject: bug#45412: File ... is large (... MiB), really open? (y)es or (n)o or (l)iterally
Date: Thu, 22 Apr 2021 00:12:54 +0200 [thread overview]
Message-ID: <m1a6prmgm1.fsf@yahoo.es> (raw)
In-Reply-To: <87mttxqgnv.fsf@gnus.org> (Lars Ingebrigtsen's message of "Sat, 17 Apr 2021 13:44:36 +0200")
[-- Attachment #1: Type: text/plain, Size: 1420 bytes --]
Lars Ingebrigtsen <larsi@gnus.org> writes:
> Daniel Martín <mardani29@yahoo.es> writes:
>
>> I've given `read-multiple-choice' a try and the help text doesn't look
>> very good if any of the descriptions is a bit long. Another problem I
>> saw is that if the help text contains a reference to a variable, the
>> rendered hyperlink doesn't work.
>>
>> It's a pity because I think this function is a good way to simplify and
>> homogenize this use case in Emacs.
>
> Well, neither problem seem insurmountable to fix.
OK, I've refactored the feature on top of a patched version of
`read-multiple-choice' that adds support for overriding the help text.
I've also handled the `edit' action, so that a user can enter a
recursive edit to select the help link. This API change is
backwards-compatible. As one change depends on the previous one, but
they are otherwise orthogonal, I've made two separate commits.
These new patches address the following review comments:
- Simplify the call site by avoiding the character loop.
- The help description now appears on `help-char', ?, or F1.
- Improves and fixes the help text and NEWS description, per Eli's
suggestions.
The idea to show the help text also for graphical prompts is a good
idea, but as there's no command already in Emacs that supports it,
AFAIK, it could be a separate feature request. What do you think?
Thanks.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Extend-read-multiple-choice-to-support-free-form-hel.patch --]
[-- Type: text/x-patch, Size: 8316 bytes --]
From d6c124930a7b54f222d3cef79e11b66eb4a188f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <mardani29@yahoo.es>
Date: Wed, 21 Apr 2021 23:14:27 +0200
Subject: [PATCH 1/2] Extend read-multiple-choice to support free-form help
descriptions
* lisp/emacs-lisp/rmc.el (read-multiple-choice): Add a new argument to
override the default help description in `read-multiple-choice'. Use
the `help-char' variable instead of ?\C-h. Also support the `edit'
action from `query-replace-map', so that help links can be visited by
entering a recursive edit.
---
lisp/emacs-lisp/rmc.el | 119 ++++++++++++++++++++++-------------------
1 file changed, 65 insertions(+), 54 deletions(-)
diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el
index bedf598d44..2c4c13ae1c 100644
--- a/lisp/emacs-lisp/rmc.el
+++ b/lisp/emacs-lisp/rmc.el
@@ -26,7 +26,7 @@
(require 'seq)
;;;###autoload
-(defun read-multiple-choice (prompt choices)
+(defun read-multiple-choice (prompt choices &optional help-string)
"Ask user a multiple choice question.
PROMPT should be a string that will be displayed as the prompt.
@@ -35,15 +35,18 @@ read-multiple-choice
be displayed while prompting (if there's room, it might be
shortened). DESCRIPTION is an optional longer explanation that
will be displayed in a help buffer if the user requests more
-help.
+help. This help description has a fixed format in columns, but
+the user can control the text that is displayed and how it is
+formatted with optional argument HELP-STRING.
This function translates user input into responses by consulting
the bindings in `query-replace-map'; see the documentation of
that variable for more information. In this case, the useful
-bindings are `recenter', `scroll-up', and `scroll-down'. If the
-user enters `recenter', `scroll-up', or `scroll-down' responses,
-perform the requested window recentering or scrolling and ask
-again.
+bindings are `recenter', `scroll-up', `scroll-down', and `edit'.
+If the user enters `recenter', `scroll-up', or `scroll-down'
+responses, perform the requested window recentering or scrolling
+and ask again. If the user enters `edit', a recursive edit is
+started.
When `use-dialog-box' is t (the default), this function can pop
up a dialog window to collect the user input. That functionality
@@ -133,6 +136,10 @@ read-multiple-choice
(ignore-errors (scroll-other-window)) t)
((eq answer 'scroll-other-window-down)
(ignore-errors (scroll-other-window-down)) t)
+ ((eq answer 'edit)
+ (save-excursion
+ (save-window-excursion
+ (recursive-edit))))
(t tchar)))
(when (eq tchar t)
(setq wrong-char nil
@@ -141,57 +148,61 @@ read-multiple-choice
;; help messages.
(when (and (not (eq tchar nil))
(not (assq tchar choices)))
- (setq wrong-char (not (memq tchar '(?? ?\C-h)))
+ (setq wrong-char (not (memq tchar '(?? help-char)))
tchar nil)
(when wrong-char
(ding))
- (with-help-window (setq buf (get-buffer-create
- "*Multiple Choice Help*"))
- (with-current-buffer buf
- (erase-buffer)
- (pop-to-buffer buf)
- (insert prompt "\n\n")
- (let* ((columns (/ (window-width) 25))
- (fill-column 21)
- (times 0)
- (start (point)))
- (dolist (elem choices)
- (goto-char start)
- (unless (zerop times)
- (if (zerop (mod times columns))
- ;; Go to the next "line".
- (goto-char (setq start (point-max)))
- ;; Add padding.
- (while (not (eobp))
- (end-of-line)
- (insert (make-string (max (- (* (mod times columns)
- (+ fill-column 4))
- (current-column))
- 0)
- ?\s))
- (forward-line 1))))
- (setq times (1+ times))
- (let ((text
- (with-temp-buffer
- (insert (format
- "%c: %s\n"
- (car elem)
- (cdr (assq (car elem) altered-names))))
- (fill-region (point-min) (point-max))
- (when (nth 2 elem)
- (let ((start (point)))
- (insert (nth 2 elem))
- (unless (bolp)
- (insert "\n"))
- (fill-region start (point-max))))
- (buffer-string))))
- (goto-char start)
- (dolist (line (split-string text "\n"))
- (end-of-line)
- (if (bolp)
- (insert line "\n")
- (insert line))
- (forward-line 1)))))))))))
+ (let ((buf (get-buffer-create "*Multiple Choice Help*")))
+ (if help-string
+ (with-help-window buf
+ (with-current-buffer buf
+ (insert help-string)))
+ (with-help-window buf
+ (with-current-buffer buf
+ (erase-buffer)
+ (pop-to-buffer buf)
+ (insert prompt "\n\n")
+ (let* ((columns (/ (window-width) 25))
+ (fill-column 21)
+ (times 0)
+ (start (point)))
+ (dolist (elem choices)
+ (goto-char start)
+ (unless (zerop times)
+ (if (zerop (mod times columns))
+ ;; Go to the next "line".
+ (goto-char (setq start (point-max)))
+ ;; Add padding.
+ (while (not (eobp))
+ (end-of-line)
+ (insert (make-string (max (- (* (mod times columns)
+ (+ fill-column 4))
+ (current-column))
+ 0)
+ ?\s))
+ (forward-line 1))))
+ (setq times (1+ times))
+ (let ((text
+ (with-temp-buffer
+ (insert (format
+ "%c: %s\n"
+ (car elem)
+ (cdr (assq (car elem) altered-names))))
+ (fill-region (point-min) (point-max))
+ (when (nth 2 elem)
+ (let ((start (point)))
+ (insert (nth 2 elem))
+ (unless (bolp)
+ (insert "\n"))
+ (fill-region start (point-max))))
+ (buffer-string))))
+ (goto-char start)
+ (dolist (line (split-string text "\n"))
+ (end-of-line)
+ (if (bolp)
+ (insert line "\n")
+ (insert line))
+ (forward-line 1)))))))))))))
(when (buffer-live-p buf)
(kill-buffer buf))
(assq tchar choices)))
--
2.31.0
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Add-a-help-option-to-the-open-large-files-prompt.patch --]
[-- Type: text/x-patch, Size: 4367 bytes --]
From 4f3e308b372cfea728211421679ad00d5a8b64df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <mardani29@yahoo.es>
Date: Wed, 21 Apr 2021 23:27:13 +0200
Subject: [PATCH 2/2] Add a help option to the open large files prompt
* lisp/files.el (files--ask-user-about-large-file-help-text): New
function that returns information about opening large files in
Emacs. (Bug#45412)
(files--ask-user-about-large-file): Use read-multiple-choice to
display the available actions.
* etc/NEWS: Advertise the new feature.
---
etc/NEWS | 4 ++++
lisp/files.el | 57 ++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index b641e8d95f..7905c936a3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -272,6 +272,10 @@ commands. The new keystrokes are 'C-x x g' ('revert-buffer'),
** Commands 'set-frame-width' and 'set-frame-height' can now get their
input using the minibuffer.
+---
+** New help window when Emacs prompts before opening a large file.
++Press '?' or 'help-char' (by default, 'C-h') to display this new help window.
+
\f
* Editing Changes in Emacs 28.1
diff --git a/lisp/files.el b/lisp/files.el
index 7440c11a21..fe3722b07d 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2123,27 +2123,56 @@ out-of-memory-warning-percentage
(declare-function x-popup-dialog "menu.c" (position contents &optional header))
+(defun files--ask-user-about-large-file-help-text (op-type size)
+ "Format the text that explains the options to open large files in Emacs.
+OP-TYPE contains the kind of file operation that will be
+performed. SIZE is the size of the large file."
+ (format
+ "The file that you want to %s is large (%s), which exceeds the
+ threshold above which Emacs asks for confirmation (%s).
+
+ Large files may be slow to edit or navigate so Emacs asks you
+ before you try to %s such files.
+
+ You can press:
+ 'y' to %s the file.
+ 'n' to abort, and not %s the file.
+ 'l' (the letter ell) to %s the file literally, which means that
+ Emacs will %s the file without doing any format or character code
+ conversion and in Fundamental mode, without loading any potentially
+ expensive features.
+
+ You can customize the option `large-file-warning-threshold' to be the
+ file size, in bytes, from which Emacs will ask for confirmation. Set
+ it to nil to never request confirmation."
+ op-type
+ size
+ (funcall byte-count-to-string-function large-file-warning-threshold)
+ op-type
+ op-type
+ op-type
+ op-type
+ op-type))
+
(defun files--ask-user-about-large-file (size op-type filename offer-raw)
(let ((prompt (format "File %s is large (%s), really %s?"
(file-name-nondirectory filename)
(funcall byte-count-to-string-function size) op-type)))
(if (not offer-raw)
(if (y-or-n-p prompt) nil 'abort)
- (let* ((use-dialog (and (display-popup-menus-p)
- last-input-event
- (listp last-nonmenu-event)
- use-dialog-box))
+ (let* ((prompt (format "File %s is large (%s), really %s?"
+ (file-name-nondirectory filename)
+ (funcall byte-count-to-string-function size) op-type))
(choice
- (if use-dialog
- (x-popup-dialog t `(,prompt
- ("Yes" . ?y)
- ("No" . ?n)
- ("Open literally" . ?l)))
- (read-char-choice
- (concat prompt " (y)es or (n)o or (l)iterally ")
- '(?y ?Y ?n ?N ?l ?L)))))
- (cond ((memq choice '(?y ?Y)) nil)
- ((memq choice '(?l ?L)) 'raw)
+ (car
+ (read-multiple-choice prompt '((?y "yes")
+ (?n "no")
+ (?l "literally"))
+ (files--ask-user-about-large-file-help-text
+ op-type
+ (funcall byte-count-to-string-function size))))))
+ (cond ((eq choice ?y) nil)
+ ((eq choice ?l) 'raw)
(t 'abort))))))
(defun abort-if-file-too-large (size op-type filename &optional offer-raw)
--
2.31.0
next prev parent reply other threads:[~2021-04-21 22:12 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-24 14:44 bug#45412: File ... is large (... MiB), really open? (y)es or (n)o or (l)iterally 積丹尼 Dan Jacobson
2020-12-25 1:00 ` Unknown
2020-12-25 1:29 ` 積丹尼 Dan Jacobson
2020-12-25 5:52 ` Lars Ingebrigtsen
2020-12-25 9:32 ` Juri Linkov
2021-04-10 22:32 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-04-10 22:52 ` Juri Linkov
2021-04-11 7:03 ` Eli Zaretskii
2021-04-12 8:06 ` Lars Ingebrigtsen
2021-04-16 23:50 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-04-17 11:44 ` Lars Ingebrigtsen
2021-04-21 22:12 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2021-04-22 10:04 ` Eli Zaretskii
2021-04-25 19:14 ` Lars Ingebrigtsen
2021-04-25 21:23 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-04-26 2:28 ` Eli Zaretskii
2021-04-27 1:08 ` Lars Ingebrigtsen
2021-05-05 23:10 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-05-06 8:28 ` Lars Ingebrigtsen
2021-05-06 8:30 ` Eli Zaretskii
2021-05-07 14:11 ` Eli Zaretskii
2021-05-08 11:37 ` Lars Ingebrigtsen
2021-05-08 12:22 ` Eli Zaretskii
2021-05-09 9:57 ` Lars Ingebrigtsen
2021-05-09 10:04 ` Eli Zaretskii
2021-04-22 22:09 ` Juri Linkov
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m1a6prmgm1.fsf@yahoo.es \
--to=bug-gnu-emacs@gnu.org \
--cc=45412@debbugs.gnu.org \
--cc=jidanni@jidanni.org \
--cc=juri@linkov.net \
--cc=larsi@gnus.org \
--cc=mardani29@yahoo.es \
/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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).