From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Drew Adams" Newsgroups: gmane.emacs.devel Subject: RE: question about `sit-for' and `C-g' Date: Sun, 13 May 2012 09:10:37 -0700 Message-ID: <8E6DA44444E8460C8A0A5B8CED61FE16@us.oracle.com> References: <5748F9CC12384B5BB267D14496E2D51E@us.oracle.com>, NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Trace: dough.gmane.org 1336925465 24899 80.91.229.3 (13 May 2012 16:11:05 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sun, 13 May 2012 16:11:05 +0000 (UTC) Cc: 'Christopher Schmidt' , emacs-devel@gnu.org To: "'Herring, Davis'" Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun May 13 18:11:04 2012 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1STbNv-0002Zr-3Y for ged-emacs-devel@m.gmane.org; Sun, 13 May 2012 18:11:03 +0200 Original-Received: from localhost ([::1]:44567 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1STbNu-0000JO-Cu for ged-emacs-devel@m.gmane.org; Sun, 13 May 2012 12:11:02 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:36728) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1STbNr-0000JJ-7f for emacs-devel@gnu.org; Sun, 13 May 2012 12:11:01 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1STbNo-0002YL-Rh for emacs-devel@gnu.org; Sun, 13 May 2012 12:10:58 -0400 Original-Received: from acsinet15.oracle.com ([141.146.126.227]:22970) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1STbNo-0002Xz-JR for emacs-devel@gnu.org; Sun, 13 May 2012 12:10:56 -0400 Original-Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by acsinet15.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id q4DGAov9008868 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sun, 13 May 2012 16:10:51 GMT Original-Received: from acsmt356.oracle.com (acsmt356.oracle.com [141.146.40.156]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q4DGAn6f018800 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 13 May 2012 16:10:50 GMT Original-Received: from abhmt104.oracle.com (abhmt104.oracle.com [141.146.116.56]) by acsmt356.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id q4DGAn1v031242; Sun, 13 May 2012 11:10:49 -0500 Original-Received: from dradamslap1 (/10.159.216.21) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 13 May 2012 09:10:49 -0700 X-Mailer: Microsoft Office Outlook 11 In-Reply-To: Thread-Index: Ac0vx/QGCsU0wCbrTcWkHNS+05g2iQADC7pgAE2MwnIAAih2QA== X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6157 X-Source-IP: acsinet22.oracle.com [141.146.126.238] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 1) X-Received-From: 141.146.126.227 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:150474 Archived-At: > > It seems that all I had to do was define a substitute for > > `sit-for' that does exactly the same thing but also binds > > `inhibit-quit' to t around the call to `read-event'. > > Or you can just do that binding around your call to `sit-for'. Of course. [But I already use a substitute for `sit-for' in Icicle mode, which checks `overriding-terminal-local-map' against `icicle-universal-argument-map', in addition to `universal-argument-map'. (The commands in the former map echo the prefix arg, which can be used separately for individual completion candidates.) And I do want `C-g' to be handled by its current keybinding for each call to `sit-for' in my code. For both of these reasons it makes sense to bind `inhibit-quit' in `icicle-sit-for'.] > At top level, C-g is bound to `keyboard-quit'. In the > minibuffer, it's typically bound to `abort-recursive-edit' > (since reading from the minibuffer is a special, unadvertised > kind of recursive edit). Yes, but neither of those is involved here. In fact, there is _no_ key binding of `C-g' that is involved. And searching Emacs Lisp and C source code for `ding', `beep', SIGQUIT, and "Quit" showed that such occurrences (and there are a _lot_ of them) are not involved either. In sum, it was not easy to find what was handling the `C-g' in this situation. I finally tracked it down to a call to `sit-for' and thus ultimately to C function `read_char'. That call to `sit-for' was so ancillary to the general user interaction in the minibuffer that I did not even think of it at first. It was only after searching unsuccessfully for what code might be intercepting the `C-g' and just printing `Quit', and a fair amount of debugging (including via `read-bell-function), that I eventually discovered the `sit-for' and its `C-g' gotcha. > Much more important, though, is > that while not in a command loop (e.g., during `sit-for'), > `quit-char' is turned directly into a `quit' signal (not > SIGQUIT; that's an unrelated Unix concept). That signal > unwinds the call stack until it hits a recursive editing > level (which catches all exceptions) and prints "Quit". Yes, that's what I was trying to say wrt the code in `read_char'. (I think you meant `quit_char', not `quit-char'. See also thread "`quit_char', `set-quit-char', and `set-input-mode'", which suggests that maybe we should have a Lisp-level equivalent of the C variable `quit_char'.) (SIGQUIT might be unrelated to a `quit' signal, but it is present quite a bit in the Emacs C code and even a bit in the Lisp code.) > From a conceptual if not a C-implementation point of view, > then, `read-char' and so forth do not handle C-g in any > special way. That is to say, it does what it always does, > and aborts the currently running Lisp code. "Aborts the currently running Lisp code" does not, in this case, mean that it returns to top level. It seems to mean that it aborts `sit-for' (?). > As it is global and standard, they do not document that behavior; > see (elisp)Quitting. Yes, I read that, of course (see bug #11458). Including this part: "Typing `C-g' while the command loop is waiting for keyboard input does not cause a quit; it acts as an ordinary input character." It could be argued that `sit-for' matches that description, at least partly, in its use of `read-event'. But it does not match the behavior described. Or rather, `read-event' & compagnie, while reading keyboard input, do not seem to just treat `C-g' as an ordinary input character, but rather they handle it directly (in addition to returning it). They seem to "cause a quit", AFAICT. Or maybe I'm not paying close enough attention to "command loop" here, and focusing on "while ... waiting for keyboard input". IOW, maybe I'm trying to read more (or less) into this passage than was meant. > > My next question is whether `sit-for' itself should do the > > same thing: bind `inhibit-quit' to t. > > Surely not. Aborting a command like yours in a normal > minibuffer would then abort the whole minibuffer (because > you'd get C-g in `unread-command-events' AND the `quit' > signal). Binding it would, and does, simply cause `C-g' in the minibuffer to do what `C-g' in the minibuffer does in general and is meant to do there: `abort-recursive-minibuffer'. TRT? Not binding it causes `C-g' to just beep and print `Quit', which is not really what a user wants, IMO. In that case, the `C-g' does not really quit anything, AFAICT, except perhaps the `sit-for' itself. What a user expects when s?he uses `C-g' in the minibuffer is `abort-recursive-edit', IMO. S?he does not know or care whether a `sit-for' might be in progress. But I won't insist that `sit-for' should simply pass the `C-g' on to the calling context so that its current binding (e.g. `abort-recursive-edit' in the minibuffer) can take effect. I only posed the question, for consideration by those of you who understand this stuff better than I. > And while it's easy to add a let-binding to get the > behavior you want, you couldn't ever go back were it the default. I have to agree with that. So part of the question I posed is whether one would ever want/need to go back. Dunno. I don't see any reason for that, offhand, but I agree that such a change to `sit-for' would remove the option (from `sit-for'). Maybe it's as simple as asking whether `C-g' during `sit-for' should quit only the `sit-for' (?), i.e., whether that is ever useful. ---- More importantly, let me just say that it took me a few _hours_ to figure out what was going on. Had _any_ of the functions I came across in my quest documented that it handled `C-g' directly as a special case (preventing it from being handled in the caller, via its key binding, etc.), then I would have found the answer (understood) immediately. (By "special case" I mean that it is treated there differently from other events/chars that are read.) That includes not only the doc strings of Lisp functions (e.g. `sit-for', `read-event'), but even the code comments for the C functions (e.g. `read_filtered_event', `read_char') - nada about `C-g'. It wasn't until I finally got to the `read_char' code that I saw anything that indicated that `C-g' was being handled. (And yes, `read_char' is something very different from `read-char'.) Looking at the code for `sit-for', unless you happen to know that `read-event' handles `C-g' directly, you (I) can easily get the impression that the `C-g' char gets pushed onto `unread-command-events'. (And that's the behavior I would in fact expect/prefer.) So yes, I disagree that this should not be documented - and yes, at the individual function level. It certainly does not hurt, IMO, to let users of a function know that a `C-g' char is handled specially there, even if this is, as you seem to say, something that people should know generally from reading (elisp `Quitting'). Anyway, I do appreciate your reply/explanation, Davis.