From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= Newsgroups: gmane.emacs.devel Subject: Re: Flymake, compilation-mode lighters very noisy Date: Wed, 21 Nov 2018 10:38:47 +0000 Message-ID: References: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="000000000000992cd6057b2a5c7c" X-Trace: blaine.gmane.org 1542796642 20448 195.159.176.226 (21 Nov 2018 10:37:22 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 21 Nov 2018 10:37:22 +0000 (UTC) Cc: emacs-devel To: Yuri Khan Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Nov 21 11:37:17 2018 Return-path: Envelope-to: ged-emacs-devel@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 1gPPsj-0005Ci-Fc for ged-emacs-devel@m.gmane.org; Wed, 21 Nov 2018 11:37:17 +0100 Original-Received: from localhost ([::1]:38226 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gPPup-0008Bd-W6 for ged-emacs-devel@m.gmane.org; Wed, 21 Nov 2018 05:39:28 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:33263) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gPPug-0008BH-SX for emacs-devel@gnu.org; Wed, 21 Nov 2018 05:39:20 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gPPuf-00062J-5n for emacs-devel@gnu.org; Wed, 21 Nov 2018 05:39:18 -0500 Original-Received: from mail-qk1-x729.google.com ([2607:f8b0:4864:20::729]:43963) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gPPue-00061o-P2 for emacs-devel@gnu.org; Wed, 21 Nov 2018 05:39:17 -0500 Original-Received: by mail-qk1-x729.google.com with SMTP id r71so4530537qkr.10 for ; Wed, 21 Nov 2018 02:39:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=DPqKC+TzIFjdLLEQn+fIX2Cstcbb+xnQj+3EfduQLAY=; b=Bk9K+HYUm7wYRlIT9C0i0YAHng0Fdla0IzSD7RTC8at+jd/pqMPIlc5+K33gaTUEOT GhqjFph2S5ln3THRXN5ETmQkBUgEmFReSBFVmVDUfLQs6Kfv/zAz2LDS/1V4wqRRX/99 f0uAraG2SWGLyBVPQm5eLSU+h0zNr24GP/5vdRBGChQrEePyA4A1s5mjdDZ6suzSDSR5 tF8R0LNQl1CglfR6ZffpiPxWJUG3MfgfsCxS0u/gIgOEYl8LXJgQIdwNLa6sD3bYZNtu 8uxiEHFn3tdYvCU1D6NKaBaMQwZ7oaghaw5TpVaWijWwc9DJ8maOPuXugNRwV4jENggp jSSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=DPqKC+TzIFjdLLEQn+fIX2Cstcbb+xnQj+3EfduQLAY=; b=R8PBkjBSFTdiBhgTjH/4O4684yuS4K0Mvq7L8VEzFiXVLuC/nQjPme0+G1rH6fyNtC 5BL+zKKc2cOVfP91awKchLYwj8ZEdH1WbwmKrDsH90CpzfszFEJMpZjDlF1rfzPzXshG j8xqYD3F+dV45AG3Jw2HIiNT/1Sb1j7CWiMo0WN+iL0DwKBMl3UMj2lnl25Ssx7813ue eWJkIR4C+IthGEJM1I7Xc+zXrxOgKmKKTXHskxWTZWSFsXZm2nOIU2GgBuSfnZAATv6I WKku2WYPVMpZahevsKSfZMz0v80Fu0XGQr6KrMB0XGScMKleigB17/21uqCKfMqJ2DDJ r9cg== X-Gm-Message-State: AA+aEWYC1Jbzp25pxbGj7AzX2miZFkartHtJe0HsO2UlYWu5G2N+7rl3 JKzXdtX8pvuoJ7IiQ2XQCxSkxTQMX9WGp91ilpY= X-Google-Smtp-Source: AFSGD/WexnEyFyOS//DZf4wcsQws2AlNIqli0DYcyUoiWRH+nxXvlvv9SAyW9dE6a8B9JYu5lPsrc/JVHIymy2nNWHg= X-Received: by 2002:ae9:d804:: with SMTP id u4mr5111753qkf.322.1542796755936; Wed, 21 Nov 2018 02:39:15 -0800 (PST) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::729 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 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" Xref: news.gmane.org gmane.emacs.devel:231275 Archived-At: --000000000000992cd6057b2a5c7c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable This is too long for me to read right now, sorry. The simple variable flymake-always-show-indicators-min-severity-level would fix the problem you reported yesterday, and it would be trivial to implement, but you seem to be suggesting much more. Propose those changes in a patch or a scratch branch! Or, alternatively, propose only the new customization variable/interfaces you would like to see added, along with docstrings, and we can deal with the implementation later after we settle on the user interface. Thanks, Jo=C3=A3o On Wed, Nov 21, 2018, 09:55 Yuri Khan On Wed, Nov 21, 2018 at 3:16 AM Jo=C3=A3o T=C3=A1vora wrote: > > >> Flymake, though, delegates the work to the function > >> =E2=80=98flymake--mode-line-format=E2=80=99, which is pretty involved = (110 lines of > >> code). Not much I can do with that, as a user, except copy-pasting > >> that function into my init.el with a minor change. > > > > To your point, propose a way to break up that function. What variable > and what semantics would you like to see? Would it be enough for a variab= le > to state the minimum severity you would want to always see, even with zer= o > occurance? In your case you would set it somewhere above "error".... If y= ou > read closely you'll find it's now at "warning", though indeed hardcoded. > > Well, as I said before, the function is =E2=80=9Cpretty involved=E2=80=9D= . That is to > say, I do not immediately understand all the things it is doing. You > are asking me to read and comprehend it. Hm, okay. > > > * I see it first calls a few functions to get the current state and > binds their results to local variables. Gonna ignore that for a > moment. It also does some data reshaping (7 lines) from the > buffer-local variable =E2=80=98flymake--backend-state=E2=80=99 into local= variable > =E2=80=98diags-by-type=E2=80=99. That could be a helper function. > > * I see it dynamically builds a mode line construct, which is always a > list. > > * Its first element is always the minor mode name, propertized to show > some statistics on mouse hover, show the mode menu on click, and show > help on middle click. This part takes 17 lines. The only dynamic > dependencies of this part are (length known), (length running), and > (length disabled). > > * The second element is nil in the normal case, but may turn into a > status item when there are no known backends, or some backends are > still running, or all backends are disabled. This part consists of a > data collection part (12 lines, binds three variables in a pcase-let) > and a conditionally applied mode line construct template (10 lines, > depends on ind, face, explain variables bound just above). > > * The last part of the function (56 lines) conditionally generates a > list of "[", followed by space-separated counters by type in > descending severity level order, followed by "]". A counter for a type > is skipped if it has no diagnostics and its severity is lower than > :warning. Each counter is a decimal number representation of the > number of diagnostics of a particular severity, propertized with the > face corresponding to the severity level, a constant mouse-face, and a > dynamically-generated keymap. The mode line construct for each counter > essentially depends on: (length diags), severity, and type. > > > So I guess what I would like to see is a better separation of logic > from presentation. Concretely, what I would do is: > > 1. Extract many variables, each of which represents a single mode line > construct used in the Flymake mode line indicator. Make them reference > any necessary data passed as values of predefined symbols. > > 2. Extract constants such as the Flymake indicator=E2=80=99s keymap as > defconsts, and near-constants such as each type=E2=80=99s counter=E2=80= =99s keymap as > defuns. > > 3. Move the decision to display or skip each element into its > corresponding data structure, possibly using the (SYMBOL THEN ELSE) > mode line construct. > > 4. The flymake-mode-line-format will be left with all the calculations > and a bunch of (format-mode-line) calls using the variables extracted > in (1), wrapped in let forms binding the necessary dynamic values to > symbols for variables to use. > > > A little code to demonstrate: > > ;;..5...10....5...20....5...30....5...40....5...50....5...60....5...70.. > ;; A user could elide zero counts from here > ;; by wrapping each (format =E2=80=A6) into a (when =E2=80=A6) > (defvar flymake-overall-indicator-help-echo-format > '((:eval (format "%d known backends\n" flymake-known-backend-count)) > (:eval (format "%d running backends\n" flymake-running-backend-count)= ) > (:eval (format "%d disabled backends\n" > flymake-disabled-backend-count)) > ("mouse-1: Display minor mode menu\n") > ("mouse-2: Show help for minor mode"))) > > (defvar flymake-overall-indicator-format > '(:propertize " Flymake" > mouse-face mode-line-highlight > help-echo flymake-overall-indicator-help-echo > keymap flymake-overall-indicator-keymap)) > > (defun flymake--mode-line-format () > (let* ((known =E2=80=A6) > =E2=80=A6more variables=E2=80=A6) > `(,(let* ((flymake-known-backend-count (length known)) > (flymake-running-backend-count (length running)) > (flymake-disabled-backend-count (length disabled)) > (flymake-overall-indicator-help-echo > (format-mode-line > flymake-overall-indicator-help-echo-format))) > (format-mode-line flymake-overall-indicator)) > =E2=80=A6more mode line constructs=E2=80=A6))) > > This way, for each element, the user gets a well-defined way to > customize when and how it appears, without having to copy the whole > function. > > > Now as to why a simple severity level variable will not cut it: The > color coding is helpful, but people with different accessibility needs > will want to replace it with different things. A color-blind user may > want to add letters, e.g. 0e 0w. A user with ADD-like symptoms will > prefer no color, with or without letters. A visually inclined user may > want to replace the string =E2=80=9CFlymake=E2=80=9D with a Unicode check= mark/info > sign/warning sign/cross. A small screen user will want to see only one > counter with the most severity, and hide warnings if there are errors. > --000000000000992cd6057b2a5c7c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
This is too long for me to read right now, sorry.

The simple variable flymake-always-sh= ow-indicators-min-severity-level would fix the problem you reported yesterd= ay, and it would be trivial to implement, but you seem to be suggesting muc= h more.

Propose those changes in a patch or a sc= ratch branch! Or, alternatively, propose only the new customization variabl= e/interfaces you would like to see added, along with docstrings, and we can= deal with the implementation later after we settle on the user interface.<= /div>

Thanks,
Jo=C3=A3o

=


=
On Wed, Nov 21, 2018, 09:55 Yuri Khan <yurivkhan@gmail.com wrote:
On Wed, Nov 21, 2018 at 3:16 AM Jo=C3=A3o T=C3=A1vora &l= t;joaotavora@gmail.com> wrote:

>> Flymake, though, delegates the work to the function
>> =E2=80=98flymake--mode-line-format=E2=80=99, which is pretty invol= ved (110 lines of
>> code). Not much I can do with that, as a user, except copy-pasting=
>> that function into my init.el with a minor change.
>
> To your point, propose a way to break up that function. What variable = and what semantics would you like to see? Would it be enough for a variable= to state the minimum severity you would want to always see, even with zero= occurance? In your case you would set it somewhere above "error"= .... If you read closely you'll find it's now at "warning"= ;, though indeed hardcoded.

Well, as I said before, the function is =E2=80=9Cpretty involved=E2=80=9D. = That is to
say, I do not immediately understand all the things it is doing. You
are asking me to read and comprehend it. Hm, okay.


* I see it first calls a few functions to get the current state and
binds their results to local variables. Gonna ignore that for a
moment. It also does some data reshaping (7 lines) from the
buffer-local variable =E2=80=98flymake--backend-state=E2=80=99 into local v= ariable
=E2=80=98diags-by-type=E2=80=99. That could be a helper function.

* I see it dynamically builds a mode line construct, which is always a list= .

* Its first element is always the minor mode name, propertized to show
some statistics on mouse hover, show the mode menu on click, and show
help on middle click. This part takes 17 lines. The only dynamic
dependencies of this part are (length known), (length running), and
(length disabled).

* The second element is nil in the normal case, but may turn into a
status item when there are no known backends, or some backends are
still running, or all backends are disabled. This part consists of a
data collection part (12 lines, binds three variables in a pcase-let)
and a conditionally applied mode line construct template (10 lines,
depends on ind, face, explain variables bound just above).

* The last part of the function (56 lines) conditionally generates a
list of "[", followed by space-separated counters by type in
descending severity level order, followed by "]". A counter for a= type
is skipped if it has no diagnostics and its severity is lower than
:warning. Each counter is a decimal number representation of the
number of diagnostics of a particular severity, propertized with the
face corresponding to the severity level, a constant mouse-face, and a
dynamically-generated keymap. The mode line construct for each counter
essentially depends on: (length diags), severity, and type.


So I guess what I would like to see is a better separation of logic
from presentation. Concretely, what I would do is:

1. Extract many variables, each of which represents a single mode line
construct used in the Flymake mode line indicator. Make them reference
any necessary data passed as values of predefined symbols.

2. Extract constants such as the Flymake indicator=E2=80=99s keymap as
defconsts, and near-constants such as each type=E2=80=99s counter=E2=80=99s= keymap as
defuns.

3. Move the decision to display or skip each element into its
corresponding data structure, possibly using the (SYMBOL THEN ELSE)
mode line construct.

4. The flymake-mode-line-format will be left with all the calculations
and a bunch of (format-mode-line) calls using the variables extracted
in (1), wrapped in let forms binding the necessary dynamic values to
symbols for variables to use.


A little code to demonstrate:

;;..5...10....5...20....5...30....5...40....5...50....5...60....5...70.. ;; A user could elide zero counts from here
;; by wrapping each (format =E2=80=A6) into a (when =E2=80=A6)
(defvar flymake-overall-indicator-help-echo-format
=C2=A0 '((:eval (format "%d known backends\n" flymake-known-b= ackend-count))
=C2=A0 =C2=A0 (:eval (format "%d running backends\n" flymake-runn= ing-backend-count))
=C2=A0 =C2=A0 (:eval (format "%d disabled backends\n" flymake-dis= abled-backend-count))
=C2=A0 =C2=A0 ("mouse-1: Display minor mode menu\n")
=C2=A0 =C2=A0 ("mouse-2: Show help for minor mode")))

(defvar flymake-overall-indicator-format
=C2=A0 '(:propertize " Flymake"
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mouse-face mode-lin= e-highlight
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 help-echo flymake-o= verall-indicator-help-echo
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 keymap flymake-over= all-indicator-keymap))

(defun flymake--mode-line-format ()
=C2=A0 (let* ((known =E2=80=A6)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=E2=80=A6more variables=E2=80=A6)
=C2=A0 =C2=A0 `(,(let* ((flymake-known-backend-count (length known))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (flymake-running-backend-c= ount (length running))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (flymake-disabled-backend-= count (length disabled))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (flymake-overall-indicator= -help-echo
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(format-mode-line fl= ymake-overall-indicator-help-echo-format)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(format-mode-line flymake-overall-indicat= or))
=C2=A0 =C2=A0 =C2=A0 =E2=80=A6more mode line constructs=E2=80=A6)))

This way, for each element, the user gets a well-defined way to
customize when and how it appears, without having to copy the whole
function.


Now as to why a simple severity level variable will not cut it: The
color coding is helpful, but people with different accessibility needs
will want to replace it with different things. A color-blind user may
want to add letters, e.g. 0e 0w. A user with ADD-like symptoms will
prefer no color, with or without letters. A visually inclined user may
want to replace the string =E2=80=9CFlymake=E2=80=9D with a Unicode check m= ark/info
sign/warning sign/cross. A small screen user will want to see only one
counter with the most severity, and hide warnings if there are errors.
--000000000000992cd6057b2a5c7c--