Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Turning display attributes on / off in prompt strings



On 17 Dec, Bart Schaefer wrote:
> On Sat, Dec 17, 2022 at 1:47 AM Oliver Kiddle <opk@xxxxxxx> wrote:
> >
> > Bart Schaefer wrote:
> > > the present prompt code would still emit the
> > > then-unnecessary sequences to restore the other attributes.
> >
> > It's probably not worth replacing the escape sequence without also
> > allowing it to avoid that because the original problem would only be
> > partially solved.
>
> Hm, I was thinking of it more as a new problem of optimization (we go
> to some lengths in other places to send the shortest possible control
> sequences).  In what way would the original problem not be solved?  An
> attribute might be turned back on after having been turned off?

The original problem was due to mixing raw sequences with prompt
sequences, right? Any time we produce \e[0m we lose everything from
the raw sequences. We could do more to send the shortest possible
control sequence. Something like %u in a prompt will always send the
off sequence regardless of whether underline was previously on. If
we optimise that, we actually make the situation worse for mixtures:
underline on might have been done as a raw sequence. The only way to
really solve that would be to parse the raw sequences.

If you search for TSC_DIRTY in prompt.c, you'll see that we restore
other attributes after not only bold off but for all of %s, %u, %B and,
of course %b. This code path is only used for prompts. You can see this
in the output of:
  print -P '%Sone%utwo'|sed -n l

The zle code does things differently. It only restores other attributes
where the use of bold ends. The implementation there is rather cleaner
in my opinion. settextattributes() is passed a zattr parameter for all
desired attributes and compares against the existing known state. Simply
by handling TXTNOBOLDFACE first, it ensures others are restored.
It'd be good to use the same interface for prompts, preferably also
dropping the "NO" forms of the flags to free up some bits to add more
attributes.

The glitch handling using the "sg" and "ug" termcap sequences also seems
to only be done for prompts but not ZLE. Do you know more about this?
Can it also be condemned to ancient history?

To optimise the control sequences to the maximum, generating sequences
should be delayed until actual text is printed but that either needs
to be added in many places or the output routines need to be wrapped.
Are there other control sequences that the current attributes affect
(scrolling up perhaps)?

> Hm, that's a bit more heavyweight than I was thinking, but would be
> the most flexible.

It is heavyweight but it already exists. I don't think the tc interface
itself is ideal because it is too low-level. Extending the interface
with something like zle -T attr doesn't necessarily need to be followed
by a function. It's a question of what sort of interface would be
useful? I think it would be best if we can assume a modern terminal
(i.e. just use \e[22m) but allow old or broken terminals to be worked
around from a shell interface. The hard part is designing that
interface.

> I presume you mean to move the transformation to the main shell and
> have zle call it?  Loading zle in non-interactive context would be
> less desirable?

The zle module could register a callback which the main shell would call
when changing attributes. Or it could be moved to a separate module.

> > * \e[22m selects normal, disabling also faint so naming indicating end
> > of bold would be a poor choice.
>
> That's true, outside of prompt context (which doesn't currently have a
> way to express "faint" without using raw sequences).  But all the
> other attributes are additive whereas faint/normal/bold are mutually
> exclusive even at the terminal level, we're not going to be able to
> make a general solution for (faint on)(bold on)(bold off) that ends in
> (faint on) state.

If you consider double underline, underline no underline or slow
blink, rapid blink, no blink then the font weight is not actually
unique in this regard. It wouldn't be a good idea for a variety of
reasons but you could in theory have:

  %bfaint%Bnormal%Bbold

While less terse, it is probably wiser to go with:

  %A{faint}faint%A{normal}normal%Bbold

Oliver




Messages sorted by: Reverse Date, Date, Thread, Author