By the way, I only asked you to propose a break up of that function because you talked about copying it to your init and tweaking it. I assumed those tweaks would not be random... :) Anyway I didn't mean to force you into reading a boring implementation detail, sorry. João On Wed, Nov 21, 2018, 10:38 João Távora 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. >> >