From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: martin rudalics Newsgroups: gmane.emacs.devel Subject: Re: "after" variable watchers Date: Mon, 24 May 2021 10:47:29 +0200 Message-ID: <400a3a6d-3fff-2eef-3fb2-0d758184bd46@gmx.at> References: <83lf8du09t.fsf@gnu.org> <3431d752-559a-7d33-e2fb-2d81dd6cc794@gmx.at> <83y2cds3g9.fsf@gnu.org> <37077232-fdf9-983c-3a34-a2334a7a8f49@gmx.at> <83sg2ho6v1.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="2474"; mail-complaints-to="usenet@ciao.gmane.io" Cc: npostavs@gmail.com, emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon May 24 10:48:55 2021 Return-path: Envelope-to: ged-emacs-devel@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 1ll6Gd-0000SA-1E for ged-emacs-devel@m.gmane-mx.org; Mon, 24 May 2021 10:48:55 +0200 Original-Received: from localhost ([::1]:60240 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ll6Gc-0004x7-3u for ged-emacs-devel@m.gmane-mx.org; Mon, 24 May 2021 04:48:54 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:52680) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ll6FO-0003B8-TT for emacs-devel@gnu.org; Mon, 24 May 2021 04:47:39 -0400 Original-Received: from mout.gmx.net ([212.227.17.21]:50931) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ll6FM-0006fU-BF; Mon, 24 May 2021 04:47:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1621846050; bh=yYZ5/3x4tcVCjDiA7W18r0Qvy+yTawbt5mi3sE3jVwc=; h=X-UI-Sender-Class:Subject:To:Cc:References:From:Date:In-Reply-To; b=EudQW+zlpy53t3X8yBFoAA+e/pyT5uHfHLTS+072pkrObqTe/XbdlJW9tHeXy+JEV OykuDq4D9x8Elwo0+oN7UVXSLra1m7MiX4d55gTPhdo7vH2ZWPSfvBM6swZZ++xfxH bCRq9w+2Q9rxQC57dU2Z2MaURX4xphSTiIvgqsEM= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Original-Received: from [192.168.1.100] ([212.95.5.110]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MaJ3t-1lz2l51tht-00WIul; Mon, 24 May 2021 10:47:30 +0200 In-Reply-To: <83sg2ho6v1.fsf@gnu.org> Content-Language: en-US X-Provags-ID: V03:K1:+BwEDOHlgebDKi+0+Bgqo8U7R4VAWxF7tAQa9CbYawye+KNwEOu AJFU7YjvT/AhBx8O1puTfUrMnRiqlb5xQ3XS1JOcK9vsQWE0zEztxk3jraALuUB/JA8s0yJ AE/91rgItrR/VGOtuHE52iYCI/kC+Xatb75cR+7HKAAY5ZUm7Om3cRhjIRHZJZ6Rd4z+o7o 42/Dzxk3i9am0qSw7T0PA== X-UI-Out-Filterresults: notjunk:1;V03:K0:vIhp1kjy3jo=:vRNSclTXppEqXsH8g6p2SG u9rPBv7Q07fJDPna490dEfwgidnFUws65ZQh4TSm5r+DbsM0AxZXPWt2ccWJD2/O50RW7LsSH WyhEjD9D6z0SwN/B4zM531saBn8oSodp6KMc9Ggc35xQ/fAJ8kAyKzfpqPTJ8dWssIlHtRxT1 tWsRQAcxa41Ny/2c68BLkg2pqq+TZHVr5DRmg7RLv9FtXMjeMZGsjl4qZemMHLMhU6NtI7t1L umVaiaviVx+pL7kK3PyDlG035zmnjCIPShqcYWkCZqIPHebfVZbaLzkBDCRjmie6ELQ7/J8so Yz9+rmb30FtqWDnW/yI86AzXkbV4HtCkDD03S++ovQ/+NoWG2+ebuL1Pk9g+azBL/O3EK/CFP NCy+XRyFk2UAOcf6zUy7VDYY9cv/Z9NWjymIEBNkGNP8DH7XgUQK6IF/LQjHFRTgsD4boXITz FHxLJLoRyIOwhrLyPDUWZtyKR3j4o2YGVwqoTJ1tjjV1czHa1elVE1CFMGUnFM44mJraL3NAU lgoSgGLfWiX6yItPmrtFORG/G4sl1uDXPorczOhXztc/06hH+izVt1knKenFs9OX69uX8vhZm sVjrTduiryku2hdYn/UPuZkjzimHbP9jx9a4tPQVT9zLUs41T7oIogAEOZH5K0wvZ593cnjX8 hS9DPm/msijEEPol9hPLbahHiXsVtzx0hH6XFXQuywaRfXOpwcprLsf3DNQHisafp70O5TNx8 Gyx8JSxFNgUpHer6MRihJj/ggcLT0fATYlUvvHs/uo9R5H2PhDHD1cb97FvwU4phYyOersZQ Received-SPF: pass client-ip=212.227.17.21; envelope-from=rudalics@gmx.at; helo=mout.gmx.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 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-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:269739 Archived-At: >> (1) The desired width of W's left fringe as set by `set-window-fringes' >> and stored in a slot w->nominal_left_fringe_width where a value of >> -1 stands for "take the width from W's buffer", > > Side note: could we please NOT call these "nominal" values? "Nominal" > means "standard", whereas these aren't. How about "desired" or > "requested"? I've been using "nominal" in the sense expressed by Wikipedia as "From a philosophical viewpoint, nominal value represents an accepted condition, which is a goal or an approximation, as opposed to the real value, which is always present.". That sentence expresses well what I'm trying to do here IMHO. >> Now suppose I assign a new value to `left-fringe-width' of W's buffer. >> >> - If I do not watch `left-fringe-width' at all, the new value will be >> picked up by redisplay the next time I call this function for some >> other reason, for example, when resizing W, unless it is preceded by a >> `set-window-buffer'. Such an effect could be surprising at least. It >> may lead to inconsistent behavior when W shall be split or resized. > > Presumably, we are now at this situation? Not really. Capturing the present situation would require to: - Forget earlier requests to set a specific window's fringe width. The value we currently store for a window's fringe width is agnostic wrt from where it was obtained from and thus cannot be restored from any nominal value once it has been configured. - Prevent applying `left-fringe-width' until set_window_buffer is run. > If so, what are the > practical problems with what we have now? We had this since many > years ago, and I'm not aware of any significant problems with what we > have. So what are the reasons for wanting such a significant new > infrastructure, if we don't have serious problems with what we have? What we have now is not what we had since "many" years ago. A window margin would shrink when dragging the divider between the window and its neighbor and become sticky after that in Emacs 24. Try with Emacs 24, set in *scratch* a `left-margin-width' of 40, do C-x 3 and drag the divider between the mode lines back and forth. Eventually, the margins in both windows will have dropped to 4 columns. Note that if, in Emacs 24, such a margin is shrunk due to shrinking its frame, it may disappear entirely. Try with a left margin width of 40 again, do C-x 3 and drag the frame's right edge to shrink the windows and expand it again. The behavior of Emacs 24 in this regard is rather unpredictable. Note also that in either case it's technically impossible to re-enlarge margins after they have shrunk because, as mentioned earlier, the origin of the configured value has been lost. With Emacs 25, splitting a window with large margins was inhibited and this became a constant source of troubles so we added the `min-margins' crutches which, to give reasonable results, have to be accompanied by an external application to handle margins widths after a window has been resized. So while the behavior of Emacs 25 became more predictable, it also introduced restrictions people didn't like and still awaits a solution for handling margins "reasonably" by default. > If your proposed "after" watcher will calculate a "sanitized" value of > w->left_fringe_width and store it in the window's structure, then why > does it have to run "after" the change? the effect of the change will > not be shown until the next redisplay cycle anyway. But other parts of our code may want to know the size of the fringes before that. Think of someone displaying a buffer in a window, setting up some decorations and trying to fit that window to its buffer. If that function used the old sizes of decorations, things may go wrong when redisplay decides to change sizes after that. Similar reasoning applies to all other functions that try to split or resize windows. >> (mapc (lambda (var) >> (add-variable-watcher var (symbol-function 'window-update-decorations-for-variable) t)) >> '(window-scale-body >> window-drop-decorations >> face-remapping-alist >> line-spacing >> min-body-width >> min-body-height >> left-fringe-width >> right-fringe-width >> fringes-outside-margins >> vertical-scroll-bar >> horizontal-scroll-bar >> scroll-bar-width >> scroll-bar-height >> left-margin-width >> right-margin-width >> mode-line-format >> header-line-format >> tab-line-format)) >> >> where most are variables that we used to have for quite some time and >> some figure here as well as in your list. > > line-spacing and face-remapping-alist don't really belong there, do > they? They do if we want to make windows sensitive to any text scaling of their buffers. The new variable `window-scale-body' tells whether to interpret the specified minimum body height (a number of lines) of a window in terms of that window's character height - which may include any line spacing - or in the line height of the window's frame. This should fix a number of bugs where people complained that Emacs always uses the frame's line height in such a case. BTW, the way to fix the behavior here is extremely hairy and much more controversial than what we are discussing in the present thread. > Likewise mode-line-format and header-line-format, AFAIR. > AFAIK, the changes in those are immediately shown by the next > redisplay. So why are they in the above list? When a window gets very small, I first want to remove its horizontal scroll bar, then its tab and header lines and keep its mode line visible as long as possible. The redisplay code then will be told to not redisplay the former. But maybe you're right here and we can get rid of these. > As for the rest: once again, what problems do we have now with changes > to them? > > Note that changes to the variables listed in frame.el do only one > thing: set a flag in the buffer's structure telling the display code > this buffer needs to be redisplayed. .. and at that time take their new values into account ... > By contrast, you want to run > complex functions when the variables are modified, and actually affect > the values stored as result. That is unheard of in Emacs; it is > almost like you are asking for having changes in some variables to > automatically run a function. Right. But I do not run a Lisp function. Though I see no harm in running a Lisp function from a variable watcher either. > Reducing the global state means we need to access variables via > accessor functions. Your suggestion goes in the exact opposite > direction: you want a change in a variable's value to have an > immediate effect, which would mean we'd need more variables to be > thread-local, or risk causing changes in the wrong buffer/thread. I have no idea how to impede having "a change in a variable's value have an immediate effect". But if you came up with an example how setting a variable could affect threading detrimentally, I might be able to understand. > Ignoring invalid changes, when this is documented, is not a > catastrophe. What makes a change invalid? A fringe width for one and the same buffer may fit into one window showing that buffer and not fit into another window showing it. That's what Emacs 27 does and I won't change that. The only thing that I intend to change is to make that fringe reappear in a window whenever that window gets large enough to show it. So we would actually do less "silent editing" than with Emacs 27 or at least not more. > Maybe I don't understand your plan, but it sounds to me > like you want to extend such silent "editing" of set values to many > more widow-related attributes; left-fringe-width was just an example, > right? Right. > and setting it to zero when unfit was also just an example, > right? The width of a fringe would always be either the requested value when it fits or zero when it does not fit. Window margins OTOH would shrink and expand dynamically. >> With my proposal, no settings are ever ignored or fixed silently. >> Decorations will grow and shrink together with their windows and frames. >> IMO this is better than, for example, showing the left margin instead of >> the window's text area when a window has become too narrow. > > I don't know if it's better. I'm mainly worried that we are trying to > invent significant infrastructure to fix problems that I don't think I Why do you think that my change to variable watchers would "invent significant infrastructure". It hardly does anything that is not already there. If an application wants to use a variable's new value and react to it immediately, it can do that already now, albeit in a less comfortable way. > understand sufficiently well, and in fact am not aware they even > exist. So maybe we should make a step back and describe and discuss > those problems first. Not processing buffer local variables immediately has surprising effects because it depends on whether `set-window-buffer' gets executed for that buffer or not. With emacs -Q consider (setq left-margin-width 20) C-x C-x or instead of C-x do C-x k. It also makes `display-buffer' inconsistent. If the buffer is already shown in a window, it does not get the new margin width, otherwise it will. Finally, it may render the results of `window-state-put' and `set-window-configuration' incompatible since the former uses `set-window-buffer' while the latter doesn't. All these imply that whenever users set one of these variables, they should call `set-window-buffer' for all windows showing the buffer right away. Just that if the window is too small and the margins don't fit, users still will not see them later even if they make enough room for them. And if they fit and a user shrinks the window, the margins might continue to occupy the entire display area of that window. martin