mirror of
https://github.com/rivo/tview.git
synced 2026-04-26 21:35:54 +03:00
[GH-ISSUE #619] Dynamic color stack #454
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/tview#454
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @marcelocantos on GitHub (Jun 12, 2021).
Original GitHub issue: https://github.com/rivo/tview/issues/619
It would be great to be able to manage dynamic color attributes with a stack, allowing pushing and popping.
Motivation
It is difficult to functionally decompose elements of a complex render. Let's say I want to underline a section of text, but that section itself has a bolded portion:
Unfortunately, the above will produce the following output, wherein the underline terminates prematurely (strike-through used in place of underline due to GitHub markdown limitations, and you'll just have to imagine the blue
foo):With a stack-based system (using the design proposed below) the above code would be:
And the output would be as intended:
Proposed design
Extend the current
[…:…:…]syntax as follows:[<fg:bg:flags]: Push the current color to the stack and set the current color to the given values, with the attributes set to the union of the current flags and specified flags (if the current setting for bold is on, then[<::u]will leave it on).[::>]: Pop the most recently pushed color and use it to set the current color.[red::b]Let's [<orange::u]do[::>] this!Colors: [<red::]R[green::]G[blue::]B[::>][<red::]red [<-::]default[::>] red again[::>]Since this is a breaking change to the syntax, an opt-in method might be needed, something like
view.SetDynamicColorWithStack(true), which would implyview.SetDynamicColor(true)(likewise, mutatis mutandis, when passingfalse).Other considerations
!could turn off the flags that follow it:[::rbl]there is [<::u!rb]little to be said[::>] about the matter([<::u!rb]preservesl, turns onuand turns offrandb).Other designs considered
"Function [blue::b]%s[-::!b] panicked", but it wouldn't handle the case that the preceding color was already set to a non-default value:"Problem reported: [red::bu]%s".[>]. However, the proposed syntax feels more balanced.[fg:bg:flags<]text[>::], but this isn't as mnemonically clear, since it places the new color outside the<…>pair.[fg:bg:flags(]text[)::], but the(…)doesn't stand out as well, due to the inner]…[pair.[pop::].[pop::]is currently equivalent to[-::]. But I'm guessing there's no existing code anywhere that relies on the current behaviour of[pop::].@rivo commented on GitHub (Nov 9, 2021):
I appreciate the detailed discussion. The current implementation is already quite complex in quite a few places. For example, in
TextView, I need to determine and store the style at the start of each line. With this proposal, it becomes more complex (and slower and more memory intensive): I'd have to store the entire stack for each line. Similarly, things get more difficult in other places, e.g. consider a right-aligned title with stacked colors that does not fit into its available space: I have to be able to split a string into a substring and preserve the stack at its boundaries. It's not impossible but the effort to make this work may cause this issue to land fairly down the todo pile. We're getting into HTML-like territory here and as mentioned elsewhere,tviewwasn't meant to replicate a browser's functionality.I'm also not quite sure if the syntax is very accessible. I mean,
[<::u!rb]little to be said[::>]looks quite complex to me. And from this part alone, I cannot tell what "little to be said" will look like because it also depends on everything that comes before.If this is something that is definitely needed by many, I would rather tend to add a "converter" to the package, something similar to
TranslateANSI()which receives text with a given syntax and translates it into colour tags used intview, basically some kind ofFlatten()function. What that syntax is supposed to be is up for discussion, it would probably make sense to find something that is already widespread. (E.g. Markdown stacks style changes, but it doesn't include background/foreground colour elements out of the box.)