From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: "Florian v. Savigny" Newsgroups: gmane.emacs.bugs Subject: bug#37906: 26.2; `call-process' docstring, section DESTINATION Date: Wed, 30 Oct 2019 16:42:03 +0100 (CET) Message-ID: <1888117473.80356.1572450123334@office.mailbox.org> References: <1640869770.32054.1571931907572@office.mailbox.org> <83pnilw6iv.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="247101"; mail-complaints-to="usenet@blaine.gmane.org" Cc: 37906@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Oct 30 16:59:19 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iPqNT-00124R-6x for geb-bug-gnu-emacs@m.gmane.org; Wed, 30 Oct 2019 16:59:19 +0100 Original-Received: from localhost ([::1]:41910 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPqNS-0002OY-3I for geb-bug-gnu-emacs@m.gmane.org; Wed, 30 Oct 2019 11:59:18 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:49900) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPqNF-0002LZ-Nr for bug-gnu-emacs@gnu.org; Wed, 30 Oct 2019 11:59:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iPqND-0003jB-HT for bug-gnu-emacs@gnu.org; Wed, 30 Oct 2019 11:59:05 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:42473) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iPqND-0003gQ-1K for bug-gnu-emacs@gnu.org; Wed, 30 Oct 2019 11:59:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iPqNC-0000MT-Vk for bug-gnu-emacs@gnu.org; Wed, 30 Oct 2019 11:59:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: "Florian v. Savigny" Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 30 Oct 2019 15:59:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 37906 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: moreinfo Original-Received: via spool by 37906-submit@debbugs.gnu.org id=B37906.15724511301355 (code B ref 37906); Wed, 30 Oct 2019 15:59:02 +0000 Original-Received: (at 37906) by debbugs.gnu.org; 30 Oct 2019 15:58:50 +0000 Original-Received: from localhost ([127.0.0.1]:51292 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iPqMz-0000Lm-HK for submit@debbugs.gnu.org; Wed, 30 Oct 2019 11:58:50 -0400 Original-Received: from mout-u-107.mailbox.org ([91.198.250.252]:50428) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iPq6x-0006La-Bz for 37906@debbugs.gnu.org; Wed, 30 Oct 2019 11:42:17 -0400 Original-Received: from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by mout-u-107.mailbox.org (Postfix) with ESMTPS id 473CPX6lK0zKnGb; Wed, 30 Oct 2019 16:42:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mailbox.org; h= content-transfer-encoding:content-type:content-type:mime-version :subject:subject:references:in-reply-to:message-id:from:from :date:date:received; s=mail20150812; t=1572450125; bh=VfdqemyTZa mVQuVzCkEeKsillRmw1zImRrJgJ9V1e+4=; b=T64R2fk7fScfmHPJ42Fqgpd5A1 fo588KeF7jmBL+pq1v8KcGxhXFFGLluXPa+OnFysBg1WpqDOy+EvHU5HrlPvoKxw zUT7fRzEoFHGalzPqrPtvJgcrO1zvQBk+fwXOm0dJn5plEyZ/gnFb9e/le8LUNrz 99YY3z4G1XJ79SVud5Q02768r7HrThKz7mssm+R4x82R+/JJsioVNSVdyDaImoJY XIlDgjM7DyREcNuNGuhcAw4ud0lj0GsJE8JUoPRIjPGaduyjmT+f+oB6wmAxKovU ost8P6sLIURlUX/57pRytrhtKgVSnCWXZxUeuCOAMXQ1N1Qu/OFJW4yNJ49g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1572450127; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZxvOKrKV+R758tckeVDCP7KnlK3dtx4zdqZ0Ug0JAs0=; b=qUDIBnO8zErqB/HbW+t7E2Bn+GMxJKJBB32rvhSk3OhwPuNP7ioA2V4Skx9SqXDlEVmLcU /TM+loXI8lq70FLs/of+2yqTqupU6339+gjAWsFbIJWkZ36/r5f755LsGMr3beAS90sX3U atlxy0+65c6d+iOa+6yJAC8ablwt7if8N2J6GpMzgSplek7Iwvj1Q6Oxrr4jo4JmSZiwXt t/DzunoibwOI7yFARYg9m223NgphdlZJqv+rbwaw9QHUIizOT+ZXJ0WhARU4Ei9VTLwKys TtiZC7KiQeEIw6nx/LYGqIpQueSGeAqm5VmQk5rcRaz/hV75c6COfoKKzi3rtQ== X-Virus-Scanned: amavisd-new at heinlein-support.de Original-Received: from smtp1.mailbox.org ([80.241.60.240]) by hefe.heinlein-support.de (hefe.heinlein-support.de [91.198.250.172]) (amavisd-new, port 10030) with ESMTP id 0FkiZCq4PIKa; Wed, 30 Oct 2019 16:42:05 +0100 (CET) In-Reply-To: <83pnilw6iv.fsf@gnu.org> X-Priority: 3 Importance: Normal X-Mailman-Approved-At: Wed, 30 Oct 2019 11:58:46 -0400 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: 209.51.188.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:170422 Archived-At: Dear Eli, I am pasting here my reply to your reply from last Friday. I realised I had= replied only to your personal E-mail address, which is probably not the ap= propriate thing to do -- I would like to apologise for that! The reply I am pasting is quite lengthy, a fact for which I would like to a= pologise, but which also underlines and illustrates that I *truly* found th= e docstring confusing. In the mean time since, however, I have realised that (I think) I CAN now n= ail down the root cause for our disparate perceptions (you finding the docs= tring clear, me finding it very confusing): Once you approach `call-process' with a different idea of what the "usual c= ase" is, as you have put it, the docstring becomes much harder to interpret= . The (actually firm) idea that I had in mind when I did "C-h f call-proces= s" was that normally, a function would keep the two output streams separate= and treat them equally, and that led to a slew of misunderstandings. (One = of the misunderstandings being that for a long time, I thought that just sp= ecifing a single value, or scalar or however it is called in Lisp, meant th= at STDERR would be discarded.) I do not want to argue what the "true" usual case is or might be. But I do = want to argue that if such an assumption is made, it should be made explici= tly (e.g. by saying, "... by default, stdout and stderr are mixed together = like on the terminal ... To handle them separately, do XY ...", or the like= ) because not doing so is tantamount to a firm assumption what the user ass= umes (and perhaps how she wants to use `call-process'), and excludes those = users for whom this assumption is wrong. Once you KNOW how the function works, it is easy to interpret the docstring= correctly. But it should be the other way round: Once you have read the do= cstring once (without having resorted to the Elisp manual), it is easy to u= se the function correctly. At least that should, as I understand it, be the= goal. As I have specified below, I think I have now found a new solution w= hich should be understandable to more people with different expectations th= an the current official one (and is even shorter), and is unambiguous. (Or = at least I hope so.) Best regards, Florian My reply from Sunday follows here: ... I hope I can be forgiven for having assumed that my suggested alternative description would speak for itself and make glaringly obvious what's (in my opinion) amiss with the docstring. I had worked through the docstring and tested the function's behaviour for something like six hours before being really confident how it behaves. And I remembered how I had read this docstring before, about 15 years ago, more or less as a complete newbie, and thought something like, "if only I had understood this back then". In other words, having to explain what I find hard to understand was about the last thing I expected, and at first, I had no idea of how to do this in writing. The only idea I was finally able to come up with is to go through the docstring step by step. I apologise this will be somewhat lengthy, but then the interface is not exactly trivial. In fact, the root (and perhaps the bigger part) of the confusion seems to me the inconsistent interface, which for most things runs counter to the everyday expectation of consistency. Nil is about the only thing tha= t has a consistent meaning; it always means "discard". But otherwise: - t means "current buffer" for stdout, but "mix with stdout" for stderr - a string means a buffer name for stdout, but a file name for stderr - as a corollary, :file is used for stdout, but not for a stderr file - only stdout has 0, such that (0 "file") is possible, but ((:file "file) 0) is not. Obviously nothing much can be done about this interface. But because of that, the documentation has to make up for that, and be extra clear and explicit. I have broken up the docstring into mouthfuls of information, and have added enumeration and itemisation to that end. I have added a comment after each mouthful as I chew on it. || like this: On working through this again, I realised (again by testing) that my understanding of the "buffer"/"buffer name" issue was still not correct. It's actually much simpler than I thought, and I have been able to come up with a new suggestion which is surprisingly short, satisfies my sense of clarity, and keeps the order you prefer. (See the end of the mail.) My first suggestion was also partly wrong. --------------------------- begin ordeal ------------------------------- Third argument DESTINATION specifies how to handle program=E2=80=99s output= . 1. If DESTINATION is a buffer, or t that stands for the current buffer, it means insert output in that buffer before point. || - ... or a buffer /name/ || (That new buffers are created even if there is not output is || also something that a newbie won't suspect. In other words, that || (s)he may have to clean up afterwards.) || || - It says only "output". Does it mean "standard output", or || "standard output mixed with standard error", in other words, "all || output, mixed"?=20 2. If DESTINATION is nil, it means discard output; 0 means discard and don=E2=80=99t wait for the program to terminate. || - It should be "all output", if you don't use the two-argument list. || || - The oddly dropped-in feature of making call-process asynchronous || via this argument certainly does not help clarity, but that is || nothing that the docstring can change. It's a bit like turning || the hindmost knob (but only that one) on your electric stove to || 1/2 (but only to that position) also turns on the central heating || for the appartment. (I know, I'm exaggerating, but still.) || || But what the docstring could say is: What happens to the || exit status if we don't wait for the program to terminate? =20 3. If DESTINATION is =E2=80=98(:file FILE)=E2=80=99, where FILE is a file n= ame string, it means that output should be written to that file (if the file already exists it is overwritten). || - Again, "all output" or "standard output"? (If used alone.) 4. DESTINATION can also have the form (REAL-BUFFER STDERR-FILE); in that case, || Why these odd placeholders, especially REAL-BUFFER? ||=20 || - stdout is REAL, why? As opposed to stderr being unreal, or || virtual??? And it can also be, as discussed above, a buffer name, || or t, or nil, or a file name, not only a BUFFER. || || - STDERR-FILE can not only be a FILE, but also t or nil. (nil is || not confusing, but t can mean stderr goes to a buffer rather than || a file.) =20 a) REAL-BUFFER says what to do with standard output, as above, while || "As above" is correct if, in what I have numbered 1. to 3., it says || "standard output", which would however be incorrect again when 1 to 3 ar= e || used alone. (I guess this is why the docstring tries to get away by sayi= ng "output" || above. But this is definitely too imprecise for "single use".) b) STDERR-FILE says what to do with standard error in the child. STDERR-FILE may be =20 - nil (discard standard error output), - t (mix it with ordinary output), or - a file name string. || The file is also overwritten, like in the case of stdout. -------------------------- end ordeal -------------------------------- So, my new suggestion would be: ---------------------------------------------------------------------- If DESTINATION is a single item, lump the program's standard output and standard error together: If it is a buffer or buffer name (or t for current buffer), insert all output in that buffer before point. If it is nil or 0, discard all output; with 0 also don=E2=80=99t wait for the program to terminate. If it is =E2=80=98(:file FILENAME)=E2=80=99 write all= output to that file (overwrite it if it already exists). If DESTINATION is a two-element list (STDOUT STDERR), keep the output streams separate. STDOUT can take the same values as detailed above (which then apply only to stdout, however). STDERR, in contrast, may only be nil (discard it), t (mix it with stdout), or the name of a file to write it to (which also gets overwritten.) ---------------------------------------------------------------------- t for STDERR is, as I just realised, completely redundant, because it specifies precisely what happens when DESTINATION is a single item. Perhaps it would be better to leave this out, if nobody needs it? I dearly hope that at the very least, my own understanding of the DESTINATION argument is completely correct now. Best regards, and thank you for bearing with me. Florian > Eli Zaretskii hat am 25. Oktober 2019 um 10:53 geschrieben= : >=20 >=20 > > Date: Thu, 24 Oct 2019 17:45:07 +0200 (CEST) > > From: "Florian v. Savigny" > >=20 > > The docstring of `call-process', which is extremely confusing (and part= ly wrong) as regards the DESTINATION argument, seems to have been in its pr= esent form for what must have been at least 15 years. Although the relevant= section in the Emacs Lisp Info does a much better job (even though I still= find the choice of "REAL-" for standard out puzzling), I would strongly su= ggest that the docstring be rewritten, too. (That would probably have consi= derably sped up my understanding of Elisp in particular and *nix systems in= general.) > >=20 > > Apart from the confusion, the docstring specifically does not acknowled= ge that e.g. (nil nil) as the DESTINATION (which might be a style somebody = chooses to be more explicit about the the use of stdout and stderr) is perf= ectly acceptable, and also e.g. (nil "file"). Even '(0 "file") will be acce= pted and work as expected.=20 > >=20 > > The following would be my suggestion as to how the relevant section cou= ld be rephrased: >=20 > Thank you for your report. >=20 > Could you please elaborate on what are the confusing parts of the > current doc string? I've re-read it now, and I think it is clear and > describes all the possible options. >=20 > E.g., the (nil nil) and (nil "file") forms are described as follows: >=20 > DESTINATION can also have the form (REAL-BUFFER STDERR-FILE); in that c= ase, > REAL-BUFFER says what to do with standard output, as above, > while STDERR-FILE says what to do with standard error in the child. > STDERR-FILE may be nil (discard standard error output), > t (mix it with ordinary output), or a file name string. >=20 > The "as above" part on the second line means that REAL-BUFFER can be > any of the values mentioned above, which includes nil. >=20 > > STDOUT can be: > > - 0: discard it and return immediately, i.e. do not even wait for the p= rogram to terminate > > - nil: discard it. > > - t: insert it into the current buffer before point. > > - a buffer name (i.e. a string): insert it into the buffer of that name= before point. > > If that buffer does not exist yet, create it (even if there is no out= put). > > - a list (:file "some_file_name"): Write it to a file called "some_file= _name". > > If the "some_file_name" exists, overwrite it, otherwise, create it. > >=20 > > STDERR can be: > > - nil: discard it. > > - t: direct it where stdout goes (mix it with stdout). > > - a file name: Write it to a file of that name, overwriting it if it ex= ists, > > otherwise creating it. > >=20 > > As shorthand for the list (STDOUT nil), i. e. when the user wants to > > discard STDERR, also accept STDOUT without a list, as detailed above. > > I.e. take e.g. '(:file "some_file_name") as '((:file "some_file_name") = nil). > >=20 > > Finally, as shorthand for '("buffer" t) (i.e. insert stdout in "buffer" > > and stderr, too), accept also the buffer of the name "buffer", without = a list.=20 >=20 > I'm not sure this is an improvement. For starters, it is longer. > More importantly, it reverses the usual case and the rare case: most > uses of call-process use what you call "shorthand", so this order > change causes the reader to have to read more, and then requires > him/her to understand what you mean by "shorthand". >=20 > So I suggest to start by describing the confusing parts. Perhaps we > can then arrive at text that will be clearer, but without the adverse > effects mentioned above. Florian v. Savigny Siebenpfeiffer Str. 25 66482 Zweibr=C3=BCcken 0175 - 365 24 17