From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Daniel =?UTF-8?Q?Mart=C3=ADn?= via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs 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 Message-ID: References: <87k0t72rhd.5.fsf@jidanni.org> <8735zuig9m.fsf@gnus.org> <87wnx62rpe.fsf@mail.linkov.net> <877dl80vwk.fsf@gnus.org> <87mttxqgnv.fsf@gnus.org> Reply-To: Daniel =?UTF-8?Q?Mart=C3=ADn?= Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="24430"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (darwin) Cc: 45412@debbugs.gnu.org, =?UTF-8?Q?=E7=A9=8D=E4=B8=B9=E5=B0=BC?= Dan Jacobson , Juri Linkov To: Lars Ingebrigtsen Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Apr 22 00:14:14 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lZL6r-0006Ch-UL for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 22 Apr 2021 00:14:14 +0200 Original-Received: from localhost ([::1]:50592 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lZL6q-0004KI-UI for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 21 Apr 2021 18:14:12 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:47648) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lZL6g-0004KA-Mr for bug-gnu-emacs@gnu.org; Wed, 21 Apr 2021 18:14:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:48469) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lZL6g-0003oJ-Cb for bug-gnu-emacs@gnu.org; Wed, 21 Apr 2021 18:14:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1lZL6g-0008Tv-7J for bug-gnu-emacs@gnu.org; Wed, 21 Apr 2021 18:14:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Daniel =?UTF-8?Q?Mart=C3=ADn?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 21 Apr 2021 22:14:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 45412 X-GNU-PR-Package: emacs Original-Received: via spool by 45412-submit@debbugs.gnu.org id=B45412.161904319132537 (code B ref 45412); Wed, 21 Apr 2021 22:14:02 +0000 Original-Received: (at 45412) by debbugs.gnu.org; 21 Apr 2021 22:13:11 +0000 Original-Received: from localhost ([127.0.0.1]:60015 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lZL5q-0008Si-Mc for submit@debbugs.gnu.org; Wed, 21 Apr 2021 18:13:11 -0400 Original-Received: from sonic303-21.consmr.mail.ir2.yahoo.com ([77.238.178.202]:43040) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lZL5m-0008SA-5z for 45412@debbugs.gnu.org; Wed, 21 Apr 2021 18:13:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.es; s=s2048; t=1619043179; bh=POV8euE30clwnqiYsk0G5F9p1kJwuGXzffr6V4uzXCI=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From:Subject:Reply-To; b=jHwfG7UQvu6zpVgLSYkxbBxDCd1SuwksvrfIA7xIIFpNcWOfnFw/N0qYtbqBsFOHdRq55mtmuRnn2ssDfwslmQ+ZXyaXlmEpn0dr9XJji4nA9CUaokej1Vy9S0jaH7VijQY9JcVZncDiyQju4H16JmDI93yi56xOy4jwgU2+WyMSVh4GiVdgSUTWCNzpD3PHunB4iuAC7zXLq0i43jkeWriwbP2IIuvuFg4JI3AVUU04MX+zWQxNXTOtk8yJnp1ExZkEof8iRgpXOyB0XAqMZ6vvH7l1GwCYnJw0tcQ+wWgICxHebapxEssCY9HoTolf8ys8awYVNkc0vLbrFUdvhw== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1619043179; bh=xXv56ELykfAIdnzf1o2HeBs0Nabsea7enUxlMdSmSwn=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=P9rMa21Vencd6Q69BpNRT9YkUsSnARFT3f6SGCWYH0ELgvC1U6zr5vSiDq384WQDw2FLRErf3VrZZr7mYhDbnvFSGdZSuMSf3nQcEt/XQ8w+8UPzA5ziUIykmapTg0Do7LjqrzliAjX4XtyYJzOk3krwmObxjdom2oTpOxcUxTfHoCjRfoVsqRPThSb3FwX6k6hzHVACl+ZMBfFWqJQKze09o0wImZ3NZcUFiGeGKJ8BUjJj4ZnZSWiVPvIluAOmHPd4/cId+JkrhOY8PFfE7f/UGx1mcCNdeQvd7JZAB5oI9YDLFr6lDhtXt0fpvTtdEjIpjdtkF/40fk9BPyutxA== X-YMail-OSG: I4PARkkVM1kzAhK1ZxqoUsde_Im9xdrwWjSlHrfVHQXzrp1kpGN20LIfl7CqpgW 46EU9793zjtTFXSMV80D81OZEfP_0dw5yqOnwxO2Vi4wmLZE_lloGRX.LY04OxsxoRqwvt.fz1pr HpHkEOjuzSJKmYlhVBXt_Sb5PoUtAIYtsDh.kOOF7aORTfEL4Z82SG15FsCv0HzE.HNBbIiUwixb mMGX8ojtXkjNBNQGz.0NwRtXxlzbTCFx2newezKQQxta4bB51V3F8T4c5La43E5.sRPD7dcBqno7 4dSXI0k27RibcYMiNN5EPHOFxeucBBOaDS1QZLnxGGZQCNGvTUoeUhsJVeFnltl_2F9rNcJe4asF 1iuxQmSf1MFVxFBWkd_lpG9RfTO3E5EF35Ihyv.V5wWKlDm_HKszLiVZ4weAJjusfkEroK4qb_Ed WNk2Nd742ok2J79q7yiKbax0ke2h.Q2qatCEkSAsAWCcHyJYmmPujSFwi3nHp0H4eQIkbYY2lfsU 1HIrDalzzgNgP9SYE.WcZRwsf26lkrpn6.7Hivlmet6K.E26F3HV1wNLLYHTy9OoVvtidRiQfnZd r_FECUiunzgjwDTfBEaogOLmM6XeoGOuz1f04IvvIqFFhhaJTMvxZehVi4kwlDYKsv4MRSeBzMhp RnQ7.pBMvK3d1jX1ZMDh_w8XwJGZ492slUkH._.Z3Q7W4I8CkjqYFOGpcSeK8GFyGqeiuZxM7Jx8 Hso6rlCXEfCflG26U1.QzRZlIgURUDdvL3VeCnbMWkI_C8N2gdnehCNodTTdR9vC.xkxSNfJ4alW 7Fn.EAWw0xjrAHW2YrXu.saqcz8g1K3Jx4rCWFJg5h X-Sonic-MF: Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic303.consmr.mail.ir2.yahoo.com with HTTP; Wed, 21 Apr 2021 22:12:59 +0000 Original-Received: by kubenode544.mail-prod1.omega.ir2.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID 4aaeda5dbcb33b1f9eaab0f654f11fdc; Wed, 21 Apr 2021 22:12:57 +0000 (UTC) In-Reply-To: <87mttxqgnv.fsf@gnus.org> (Lars Ingebrigtsen's message of "Sat, 17 Apr 2021 13:44:36 +0200") X-Mailer: WebService/1.1.18121 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.yahoo Apache-HttpAsyncClient/4.1.4 (Java/16) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:204665 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Lars Ingebrigtsen writes: > Daniel Mart=C3=ADn 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. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Extend-read-multiple-choice-to-support-free-form-hel.patch >From d6c124930a7b54f222d3cef79e11b66eb4a188f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= 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 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Add-a-help-option-to-the-open-large-files-prompt.patch >From 4f3e308b372cfea728211421679ad00d5a8b64df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= 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. + * 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 --=-=-=--