From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Tino Calancha Newsgroups: gmane.emacs.bugs Subject: bug#28525: 26.0.60; dired-delete-file: Accept y/n if yes-or-no-p is aliased to y-or-n-p Date: Sat, 30 Sep 2017 22:00:46 +0900 Message-ID: <87tvzktk75.fsf@gmail.com> References: <87mv5pn1dz.fsf@calancha-pc> <83zi9oeacc.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: blaine.gmane.org 1506776539 22306 195.159.176.226 (30 Sep 2017 13:02:19 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 30 Sep 2017 13:02:19 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) Cc: npostavs@users.sourceforge.net, 28525@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Sep 30 15:02:14 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dyHPJ-0005Qb-JA for geb-bug-gnu-emacs@m.gmane.org; Sat, 30 Sep 2017 15:02:13 +0200 Original-Received: from localhost ([::1]:39274 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dyHPQ-0006CZ-V2 for geb-bug-gnu-emacs@m.gmane.org; Sat, 30 Sep 2017 09:02:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:54700) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dyHPD-0006CP-Qt for bug-gnu-emacs@gnu.org; Sat, 30 Sep 2017 09:02:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dyHP8-0000zL-PA for bug-gnu-emacs@gnu.org; Sat, 30 Sep 2017 09:02:07 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:59679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dyHP8-0000z4-LC for bug-gnu-emacs@gnu.org; Sat, 30 Sep 2017 09:02:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dyHP8-0002d7-AG for bug-gnu-emacs@gnu.org; Sat, 30 Sep 2017 09:02:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Tino Calancha Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Sep 2017 13:02:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 28525 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 28525-submit@debbugs.gnu.org id=B28525.150677646810045 (code B ref 28525); Sat, 30 Sep 2017 13:02:02 +0000 Original-Received: (at 28525) by debbugs.gnu.org; 30 Sep 2017 13:01:08 +0000 Original-Received: from localhost ([127.0.0.1]:40127 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dyHOE-0002bv-BQ for submit@debbugs.gnu.org; Sat, 30 Sep 2017 09:01:08 -0400 Original-Received: from mail-pf0-f175.google.com ([209.85.192.175]:49622) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dyHOB-0002bJ-Ii for 28525@debbugs.gnu.org; Sat, 30 Sep 2017 09:01:04 -0400 Original-Received: by mail-pf0-f175.google.com with SMTP id l188so1014635pfc.6 for <28525@debbugs.gnu.org>; Sat, 30 Sep 2017 06:01:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version:content-transfer-encoding; bh=5/XN2wuhlqhfra99joqXAuP168DzRLFBAlb9JKQKhr8=; b=C6oWy53MAGYJ4oHiquZvb1NxxJcSwDcGZYV08JGQiLa2MAmRBvtO9A2b7mLZTAViPM FjJN7d1d07C1ToKLCo525WdNGJKdY2hgXaZjACaJ9EmlRlCZJ7WxEvDNgtPv1BtKmlTR x8s91ZbOVRZbJ9a1HnHeS2RNS3zvah2N+uwVmKEudzNOQOf3+3TOZ6oQUHQmL59GO7dl l8ho5mv35Dgm5VsfyPjsBPB+b5xk5O56q9+XRMt1s3LDTMr9OEqWWl1DXpIS5BesCZmq VPD45ceMmMB7l0eXFBfy0H/tzWLUx0bLeGKH/gjR8ZP5ka4n1tJBNHNP04efTnoXZM4c 1ZOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-transfer-encoding; bh=5/XN2wuhlqhfra99joqXAuP168DzRLFBAlb9JKQKhr8=; b=M2WjEV/OiunxTNf0fBShVx1vF16zb27uGqehubPmiollw2O3HzlRKDSMGoqdn+kcJl 5biTSCdRP/yzNNPehUNkflqjNrWqL0byMdzVK4xM29SiNT7OThsyLjkQqbkm4TMaSELM 45r1zPPxD2ldPrFV5RrGfGGJqtWKunI7HrNjmt8PgIayUlshBNOXyXhwmo/jwaaSjBnk YL3e1aLRwR4kkVE4X9ALogOIvz/A9q9Yif9D6WazbLEfJguABos6dVD2LQv8cp4u5LRD dsWMDui+2CYVaYi8zyNTiP8DOJ+wd9RgTOLUvu/s6u/l0G++qanWRT1LOzL20dRI5gHZ kILA== X-Gm-Message-State: AHPjjUiTAPFsu5Kuu2pk7wAotJ2pdtfXn+68MEpX+sHhFQMbn7E07J9r /y89FyyjmXSWwaBAlCNrzZH+XQ== X-Google-Smtp-Source: AOwi7QDJlDi9YSueUNZm1a/RkLaznQsSW+GgPdQhp8lBtkD0cULoQWcRaMv2RNEPwMGuBNddHzPhOA== X-Received: by 10.98.137.150 with SMTP id n22mr10448877pfk.104.1506776457025; Sat, 30 Sep 2017 06:00:57 -0700 (PDT) Original-Received: from calancha-pc (203.191.218.133.dy.bbexcite.jp. [133.218.191.203]) by smtp.gmail.com with ESMTPSA id o128sm9114762pga.5.2017.09.30.06.00.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 30 Sep 2017 06:00:55 -0700 (PDT) In-Reply-To: <83zi9oeacc.fsf@gnu.org> (Eli Zaretskii's message of "Thu, 21 Sep 2017 11:15:31 +0300") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 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.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:137677 Archived-At: Eli Zaretskii writes: >> dired-do-delete: Allow to delete dirs recursively without prompts >> (cbea38e5c4af5386192fb9a48ef4fca5080d6561) >>=20 >> doesn't consider the case when an user has aliased 'yes-or-no-p' >> to 'y-or-n-p'. That's annoying if you are used to the previous >> behaviour. > > People who make such aliases will have to change their aliases to > support the 3rd option, right. What function would they use for that? > Does such a function exist? If it doesn't exist, then what is the > complaint wrt this change, exactly? In my previous patch i checked if `yes-or-no-p' is aliased to `y-or-n-p'. A more general way is to add new functions `yes-or-no-or-else-p', `y-or-n-or-else-p': they ask the question and accept additional answers according with an optional argument. Then we could rewrite the feature using `yes-or-no-or-else-p'. Users might do: (fset 'yes-or-no-or-else-p 'y-or-n-or-else-p) so that they can answer just 'y' or 'n' as before, or even answer '!' to accept all. (yes-or-no-or-else-p "Do it? " '((! . automatic) (\? . help))) (y-or-n-or-else-p "Do it? " '((! . automatic) (\? . help))) The former accepts answers: yes, no, automatic, help The latter accepts: y, n, !, ? > We can be asked to do one of the following: > > . continue supporting y-or-n-p as a defalias of yes-or-no-p, with > the understanding that the users who do that will not have a way > to use the new functionality; or > . allow users to specify a function that accepts single-key > responses, like y-or-n-p, but also allows to select the new > functionality, e.g., with '!' > The solution in each of these cases is different. So we should first > decide which problem are we trying to solve. I prefer the second option. I guess it must be easy to write using `yes-or= -no-or-else-p'. --8<-----------------------------cut here---------------start------------->= 8--- commit 47164987830769282f690a3c3fd9ee36772d5d12 Author: Tino Calancha Date: Sat Sep 30 21:51:55 2017 +0900 New functions: yes-or-no-or-else-p and y-or-n-or-else-p =20=20=20=20 * src/fns.c (yes-or-no-else-p): New defun. (yes-or-no-p): Use it. * lisp/subr.el (y-or-n-or-else-p): Like y-or-n-p with more possible answers specified by arg OTHERS. (y-or-n-p): Use it. diff --git a/lisp/subr.el b/lisp/subr.el index cf15ec287f..6f3f5dabfd 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2484,73 +2484,65 @@ sit-for ;; Behind display-popup-menus-p test. (declare-function x-popup-dialog "menu.c" (position contents &optional hea= der)) =20 -(defun y-or-n-p (prompt) - "Ask user a \"y or n\" question. -Return t if answer is \"y\" and nil if it is \"n\". -PROMPT is the string to display to ask the question. It should -end in a space; `y-or-n-p' adds \"(y or n) \" to it. - -No confirmation of the answer is requested; a single character is -enough. SPC also means yes, and DEL means no. - -To be precise, 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 `act', `skip', `recenter', -`scroll-up', `scroll-down', and `quit'. -An `act' response means yes, and a `skip' response means no. -A `quit' response means to invoke `keyboard-quit'. -If the user enters `recenter', `scroll-up', or `scroll-down' -responses, perform the requested window recentering or scrolling -and ask again. - -Under a windowing system a dialog box will be used if `last-nonmenu-event' -is nil and `use-dialog-box' is non-nil." - ;; =C2=A1Beware! when I tried to edebug this code, Emacs got into a weir= d state - ;; where all the keys were unbound (i.e. it somehow got triggered - ;; within read-key, apparently). I had to kill it. - (let ((answer 'recenter) - (padded (lambda (prompt &optional dialog) - (let ((l (length prompt))) - (concat prompt - (if (or (zerop l) (eq ?\s (aref prompt (1- l)))) - "" " ") - (if dialog "" "(y or n) ")))))) +(defun y-or-n-or-else-p (prompt &optional others) + "Ask user a \"y or n or ...\" question. +OTHERS is a list (INPUT . ACTION), with INPUT the user +input, and ACTION determines how to proceed; both are symbols. +For instance, SYMBOL might be '!' and ACTION 'automatic'. + +This is like `y-or-n-p' with the additional answers in OTHERS." + (let* ((answer 'recenter) + (options (mapcar #'car others)) + (options-str (mapconcat #'identity + (append (list "y" "n") + (mapcar (lambda (x) (symbol-name (car= x))) others)) " or ")) + (actions (append '(skip act) (mapcar #'cdr others))) + (padded (lambda (prompt &optional dialog) + (let ((l (length prompt))) + (concat prompt + (if (or (zerop l) (eq ?\s (aref prompt (1- l)))) + "" " ") + (if dialog "" (concat "(" options-str ")"))))))) (cond (noninteractive (setq prompt (funcall padded prompt)) (let ((temp-prompt prompt)) - (while (not (memq answer '(act skip))) + (while (not (memq answer actions)) (let ((str (read-string temp-prompt))) (cond ((member str '("y" "Y")) (setq answer 'act)) + ((assoc (intern str) others) (setq answer (cdr (assoc (i= ntern str) others)))) ((member str '("n" "N")) (setq answer 'skip)) - (t (setq temp-prompt (concat "Please answer y or n. " + (t (setq temp-prompt (concat "Please answer " options-str ". " prompt)))))))) ((and (display-popup-menus-p) last-input-event ; not during startup (listp last-nonmenu-event) use-dialog-box) (setq prompt (funcall padded prompt t) - answer (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip))))) + answer + (x-popup-dialog + t + `(,prompt ("Yes" . act) ("No" . skip) + (mapcar (lambda (x) (cons (symbol-name (car x)) (cd= r x))) others))))) (t (setq prompt (funcall padded prompt)) (while (let* ((scroll-actions '(recenter scroll-up scroll-down - scroll-other-window scroll-other-window-down)) + scroll-other-window scroll-other-window-down)) (key (let ((cursor-in-echo-area t)) (when minibuffer-auto-raise (raise-frame (window-frame (minibuffer-window)))) (read-key (propertize (if (memq answer scroll-actions) prompt - (concat "Please answer y or n.= " - prompt)) + (concat "Please answer " optio= ns-str ". " prompt)) 'face 'minibuffer-prompt))))) (setq answer (lookup-key query-replace-map (vector key) t)) (cond - ((memq answer '(skip act)) nil) - ((eq answer 'recenter) - (recenter) t) + ((memq answer actions) nil) + ((member (intern (char-to-string key)) options) + (setq answer (cdr (assoc (intern (char-to-string key)) other= s))) nil) + ((eq answer 'recenter) (recenter) t) ((eq answer 'scroll-up) (ignore-errors (scroll-up-command)) t) ((eq answer 'scroll-down) @@ -2564,11 +2556,43 @@ y-or-n-p (t t))) (ding) (discard-input)))) - (let ((ret (eq answer 'act))) + (let ((ret (cond ((eq answer 'act)) + ((eq answer 'skip) nil) + ((memq answer actions) answer)))) (unless noninteractive - (message "%s%c" prompt (if ret ?y ?n))) + (message "%s%c" prompt (cond ((eq ret t) ?y) + ((null ret) ?n) + ((memq ret actions) + (string-to-char (symbol-name (car (r= assoc ret others)))))))) ret))) =20 +(defun y-or-n-p (prompt) + "Ask user a \"y or n\" question. +Return t if answer is \"y\" and nil if it is \"n\". +PROMPT is the string to display to ask the question. It should +end in a space; `y-or-n-p' adds \"(y or n) \" to it. + +No confirmation of the answer is requested; a single character is +enough. SPC also means yes, and DEL means no. + +To be precise, 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 `act', `skip', `recenter', +`scroll-up', `scroll-down', and `quit'. +An `act' response means yes, and a `skip' response means no. +A `quit' response means to invoke `keyboard-quit'. +If the user enters `recenter', `scroll-up', or `scroll-down' +responses, perform the requested window recentering or scrolling +and ask again. + +Under a windowing system a dialog box will be used if `last-nonmenu-event' +is nil and `use-dialog-box' is non-nil." + ;; =C2=A1Beware! when I tried to edebug this code, Emacs got into a weir= d state + ;; where all the keys were unbound (i.e. it somehow got triggered + ;; within read-key, apparently). I had to kill it. + (y-or-n-or-else-p prompt)) + ;;; Atomic change groups. =20 diff --git a/src/fns.c b/src/fns.c index 4524ff9b26..5eee5d380f 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2582,20 +2582,27 @@ do_yes_or_no_p (Lisp_Object prompt) return call1 (intern ("yes-or-no-p"), prompt); } =20 -DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0, - doc: /* Ask user a yes-or-no question. -Return t if answer is yes, and nil if the answer is no. +DEFUN ("yes-or-no-or-else-p", Fyes_or_no_or_else_p, Syes_or_no_or_else_p, = 1, 2, 0, + doc: /* Ask user a yes or no or ... question. +OTHERS is a list (INPUT . ACTION), with INPUT the user +input, and ACTION determines how to proceed; both are symbols. +For instance, SYMBOL might be '!' and ACTION 'automatic'. + +Return t if answer is yes, nil if the answer is no or ACTION if the answer +is ACTION. PROMPT is the string to display to ask the question. It should end in -a space; `yes-or-no-p' adds \"(yes or no) \" to it. +a space; `yes-or-no-or-else-p' adds \"(yes or no or ACTION1 or ACTION2 ...= ) \" to it. =20 The user must confirm the answer with RET, and can edit it until it has been confirmed. =20 If dialog boxes are supported, a dialog box will be used -if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */) - (Lisp_Object prompt) +if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. + +This function is like `yes-or-no-p' with the additional answers in OTHERS.= */) + (Lisp_Object prompt, Lisp_Object others) { - Lisp_Object ans; + Lisp_Object ans, yes_or_no, actions, str; =20 CHECK_STRING (prompt); =20 @@ -2611,9 +2618,21 @@ if `last-nonmenu-event' is nil, and `use-dialog-box'= is non-nil. */) return obj; } =20 - AUTO_STRING (yes_or_no, "(yes or no) "); - prompt =3D CALLN (Fconcat, prompt, yes_or_no); - + if (!NILP (others)) { + actions =3D Fmapcar (intern ("symbol-name"), Fmapcar (Qcdr, others)); + yes_or_no =3D Fmapconcat (Qidentity, + CALLN (Fappend, list2 (build_string ("yes"), + build_string ("no")), + actions), + build_string (" or ")); + yes_or_no =3D CALLN (Fconcat, build_string ("("), yes_or_no, build_str= ing (")")); + } + else { + actions =3D Qnil; + yes_or_no =3D build_string ("(yes or no)"); + } + prompt =3D CALLN (Fconcat, prompt, yes_or_no, build_string (" ")); + str =3D CALLN (Fconcat, build_string ("Please answer "), yes_or_no, buil= d_string (".")); while (1) { ans =3D Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil, @@ -2623,13 +2642,31 @@ if `last-nonmenu-event' is nil, and `use-dialog-box= ' is non-nil. */) return Qt; if (SCHARS (ans) =3D=3D 2 && !strcmp (SSDATA (ans), "no")) return Qnil; + if (!NILP (Fmember (ans, actions))) + return Fcdr (Frassoc (intern (SSDATA (ans)), others)); =20 Fding (Qnil); Fdiscard_input (); - message1 ("Please answer yes or no."); + message1 (SSDATA (str)); Fsleep_for (make_number (2), Qnil); } } + +DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0, + doc: /* Ask user a yes-or-no question. +Return t if answer is yes, and nil if the answer is no. +PROMPT is the string to display to ask the question. It should end in +a space; `yes-or-no-p' adds \"(yes or no) \" to it. + +The user must confirm the answer with RET, and can edit it until it +has been confirmed. + +If dialog boxes are supported, a dialog box will be used +if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */) + (Lisp_Object prompt) +{ + return Fyes_or_no_or_else_p (prompt, Qnil); +} DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0, doc: /* Return list of 1 minute, 5 minute and 15 minute load averag= es. @@ -5273,6 +5310,7 @@ this variable. */); defsubr (&Smapcan); defsubr (&Smapconcat); defsubr (&Syes_or_no_p); + defsubr (&Syes_or_no_or_else_p); defsubr (&Sload_average); defsubr (&Sfeaturep); defsubr (&Srequire); --8<-----------------------------cut here---------------end--------------->= 8--- In GNU Emacs 27.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11) of 2017-09-29 Repository revision: 20a09de953f437109a098fa8c4d380663d921481