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ão On Wed, Nov 21, 2018, 09:55 Yuri Khan On Wed, Nov 21, 2018 at 3:16 AM João Távora wrote: > > >> Flymake, though, delegates the work to the function > >> ‘flymake--mode-line-format’, 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 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 “pretty involved”. 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 ‘flymake--backend-state’ into local variable > ‘diags-by-type’. 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’s keymap as > defconsts, and near-constants such as each type’s counter’s 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 …) into a (when …) > (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 …) > …more variables…) > `(,(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)) > …more mode line constructs…))) > > 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 “Flymake” 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. >