content-model

Text Content Model

In order to support many use cases securely, Terminal::Widgets has a somewhat complex content model internally, with simpler interfaces built on those internals that the app developer can use confidently.

Layering and Conversions

To support all the different desired use cases, Terminal::Widgets uses a hierarchy of text content types, each convertible to the next. Here's an example of the process, starting from a TranslatableString:

TranslatableString — 'It is not ${c:important|diagnosis}.'
  │
  ā–¼
MarkupString       — 'Itway isway otnay ${c:important|diagnosis}.'
  │
  ā–¼
SpanTree           — SpanTree(StringSpan('Itway isway otnay '),
  │                           InterpolantSpan(var   => 'diagnosis',
  │                                           class => 'important'),
  │                           StringSpan('.'))
  ā–¼
Array[StringSpan]  — [StringSpan('Itway isway otnay '),
  │                   StringSpan('ibblestray',
  │                              attributes => %(:important, :interpolation)),
  │                   StringSpan('.')]
  ā–¼
Array[RenderSpan]  — [RenderSpan('',         'Itway isway otnay '),
  │                   RenderSpan('bold red', 'ibblestray'),
  │                   RenderSpan('',         '.')]
  ā–¼
Str                — 'Itway isway otnay ibblestray.'

Here's what the conversion pipeline looks like under the covers:

TranslatableString — Highest level, opaque (though often in source language)
  │
  │ .translate       āš™ļø Look up translated variant that matches interpolant vars
  ā–¼
MarkupString       — Includes inline semantic markup of spans and interpolants
  │
  │ .parse           āš™ļø Parse markup into a tree of typed spans
  ā–¼
SpanTree           — Tree of SemanticSpans (InterpolantSpan or StringSpan)
  │
  │ .flatten         āš™ļø Flatten tree into single list of SemanticSpans
  │
  │ .interpolate     āš™ļø Interpolate variables into InterpolantSpans
  ā–¼
Array[StringSpan]  — Flattened (and if necessary interpolated) renderable spans
  │
  │ .render          āš™ļø Render (StringSpan + attributes) into (RenderSpan + color)
  ā–¼
Array[RenderSpan]  — Flat array of RenderSpans for Widget.draw-line-spans
  │
  │ plain-text()     āš™ļø (OPTIONAL) Join text from RenderSpans into a plain Str
  ā–¼
Str                — Just a plain string, for use where color doesn't matter

Performance

While every attempt has been made to make individual operations efficient, it's obvious that a long pipeline will build up overhead, and some operations may be slow enough to be prohibitive when dealing with high volumes of text content. It is rarely necessary however to repeat the early stages of the pipeline on every screen refresh. Translations for strings that don't contain any interpolations will generally be static per language for a given software release, for example.

Thus ContentRenderer and its subclass TranslatableContentRenderer provide convenience methods that will drive rendering starting at any point in the render pipeline and ending at any point farther along. This both improves testability/debuggability, and allows caching of partially-completed rendering work.

Security

It is a critical design feature that the render pipeline is one way. This prevents a number of security and correctness bugs that would be caused by for instance accidentally parsing markup within the results of a variable interpolation.

Furthermore TranslatableString and MarkupString both default to NOT allowing generation of InterpolantSpans, so string contents that only coincidentally contain variable interpolation markup pose no threat. The programmer must explicitly mark a string as interpolatable out of band to turn this functionality on.

All of the semantic classes (those other than Str and RenderSpan) throw a special exception X::CannotStringify if an attempt is made to stringify them without going through the proper stages of the conversion pipeline.

Terminal::Widgets v0.3.2

Basic TUI Widgets

Authors

  • Geoffrey Broadwell

License

Artistic-2.0

Dependencies

Color::DirColors:auth<zef:japhb>:ver<0.0.3+>Terminal::ANSIColor:ver<0.14+>:auth<zef:raku-community-modules>Terminal::Capabilities:auth<zef:japhb>:ver<0.0.21+>Terminal::LineEditor:auth<zef:japhb>:ver<0.0.23+>Terminal::Print:auth<zef:terminal-printers>:ver<0.977+>Text::MiscUtils:auth<zef:japhb>:ver<0.0.13+>nano:auth<zef:lizmat>:ver<0.0.2+>

Test Dependencies

Provides

  • Terminal::Widgets
  • Terminal::Widgets::App
  • Terminal::Widgets::ColorTheme
  • Terminal::Widgets::ColorThemes
  • Terminal::Widgets::Common
  • Terminal::Widgets::DirtyAreas
  • Terminal::Widgets::Events
  • Terminal::Widgets::Focusable
  • Terminal::Widgets::Form
  • Terminal::Widgets::I18N::Locale
  • Terminal::Widgets::I18N::Translation
  • Terminal::Widgets::Input
  • Terminal::Widgets::Input::Boolean
  • Terminal::Widgets::Input::Button
  • Terminal::Widgets::Input::Checkbox
  • Terminal::Widgets::Input::Labeled
  • Terminal::Widgets::Input::Menu
  • Terminal::Widgets::Input::RadioButton
  • Terminal::Widgets::Input::SimpleClickable
  • Terminal::Widgets::Input::Text
  • Terminal::Widgets::Input::ToggleButton
  • Terminal::Widgets::Layout
  • Terminal::Widgets::Layout::BoxModel
  • Terminal::Widgets::PlainText
  • Terminal::Widgets::Progress::Tracker
  • Terminal::Widgets::ScrollBar
  • Terminal::Widgets::Scrollable
  • Terminal::Widgets::Simple
  • Terminal::Widgets::Simple::App
  • Terminal::Widgets::Simple::StandardWidgets
  • Terminal::Widgets::Simple::TopLevel
  • Terminal::Widgets::SpanBuffer
  • Terminal::Widgets::Terminal
  • Terminal::Widgets::TextContent
  • Terminal::Widgets::Themable
  • Terminal::Widgets::TopLevel
  • Terminal::Widgets::Utils
  • Terminal::Widgets::Utils::Color
  • Terminal::Widgets::Viewer::DirTree
  • Terminal::Widgets::Viewer::Log
  • Terminal::Widgets::Viewer::RichText
  • Terminal::Widgets::Viewer::Tree
  • Terminal::Widgets::Viz::SmokeChart
  • Terminal::Widgets::Viz::Sparkline
  • Terminal::Widgets::Volatile::DirTree
  • Terminal::Widgets::Volatile::Tree
  • Terminal::Widgets::Widget
  • Terminal::Widgets::WidgetRegistry
  • Terminal::Widgets::WrappableBuffer

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.