<commit_before>\section{Text}
\label{sec:text}

The \fw{Text} module provides a widget for rendering text strings in
user interfaces.  The text widget type, \fw{Widget FormattedText}, can
be used to render simple strings or more complex text arrangements.

A \fw{FormattedText} widget can be created from a \fw{String} with the
\fw{plainText} function and can be laid out in the usual way:

\begin{haskellcode}
 t1 <- plainText "blue" >>= withNormalAttribute (fgColor blue)
 t2 <- plainText "green" >>= withNormalAttribute (fgColor green)
 ui <- (return t1) <++> (return t2)
\end{haskellcode}

\subsection{Formatters}

In addition to rendering plain text strings, we can use ``formatters''
to change the arrangement and attributes of text.  Formatters can
manipulate structure and attributes to change the text layout and
appearance.

To use a formatter with a text widget, we must use a different
constructor function, \fw{text\-Widget}:

\begin{haskellcode}
 t <- textWidget wrap "foobar"
\end{haskellcode}

When formatters are applied, the text is automatically broken up into
``tokens,'' each of which indicates sequences of whitespace or
non-whitespace characters.  Each token stores its own attribute and it
is these tokens on which formatters operate.

The \fw{Text} module provides two formatters: \fw{wrap} and
\fw{highlight}.  \fw{wrap} wraps the text to fit into the
\fw{DisplayRegion} available at rendering time.  \fw{highlight} uses
the \fw{pcre-light}\footnote{\fw{pcre-light} on Hackage:
  \href{http://hackage.haskell.org/package/pcre-light-0.3.1.1}{http://hackage.haskell.org/package/pcre-light-0.3.1.1}}
library to highlight text using ``Perl-compatible'' regular
expressions.  To construct a highlighting formatter, we must provide
the regular expression used to match strings as well as the attribute
that should be applied to the matches:\footnote{Since
  formatters operate on individual tokens, the \fw{highlight}
  formatter applies its regular expression to each token individually,
  so it will only ever match sequences of characters in each token
  rather than matching more than one token.}

\begin{haskellcode}
 let doHighlight = highlight (compile (pack "bar") [])
                     (fgColor bright_green)
 t <- textWidget doHighlight "Foo bar baz"
\end{haskellcode}

Formatters can be composed with the \fw{\&.\&} operator.  This
operator constructs a new formatter which will apply the operand
formatters in the specified order.  We can use this operator to
compose the built-in formatters on a single \fw{FormattedText} widget:

\begin{haskellcode}
 t <- textWidget (doHighlight &.& wrap) "Foo bar baz"
\end{haskellcode}

\subsubsection{Growth Policy}

\fw{FormattedText} widgets do not grow horizontally or vertically.<commit_msg>Manual: add Text sections on updating text widgets, fix old material to reflect new API<commit_after>\section{Text}
\label{sec:text}

The \fw{Text} module provides a widget for rendering text strings in
user interfaces.  The text widget type, \fw{Widget FormattedText}, can
be used to render simple strings or more complex text arrangements.

A \fw{FormattedText} widget can be created from a \fw{String} with the
\fw{plainText} function and can be laid out in the usual way:

\begin{haskellcode}
 t1 <- plainText "blue" >>= withNormalAttribute (fgColor blue)
 t2 <- plainText "green" >>= withNormalAttribute (fgColor green)
 ui <- (return t1) <++> (return t2)
\end{haskellcode}

\subsection{Updating Text Widgets}
\label{sec:updatingText}

The contents of a text widget can be set in one of three ways:
\begin{itemize}
\item Initially, as a parameter to \fw{plainText} and \fw{textWidget}
\item As a \fw{String} parameter to \fw{setText}
\item As a list parameter of \fw{(String, Attr)} with
  \fw{setTextWithAttrs}
\end{itemize}

All text widget update functions \textit{tokenize} their inputs,
finding contiguous sequences of whitespace and non-whitespace
characters and newlines, and store the list of tokens in the widget.
Each token is assigned a default attribute of \fw{def\_attr}, which
defaults to the ``normal'' attribute of the widget (see Section
\ref{sec:attributes} for more information on attributes).

The \fw{setText} function merely takes a \fw{String}, tokenizes it,
and assigns the default attribute to all tokens.

The \fw{setTextWithAttrs} function provides finer control over the
initial attribute assignment to the text because it lets you specify
the initial contents of the widget with your own attribute
assignments.  This can be done instead of (or in addition to) the use
of formatters for maximum control over the final visual representation
of the text.

In the following example, we create a text widget and then assign it a
string with different attributes for each of the words:

\begin{haskellcode}
 t <- plainText ""
 setTextWithAttrs t [ ("foo", fgColor green)
                    , (" ", def_attr)
                    , ("bar", fgColor yellow)
                    , (" ", def_attr)
                    , ("baz", red `on` blue)
                    ]
\end{haskellcode}

\subsection{Formatters}

In addition to rendering plain text strings, we can use ``formatters''
to change the arrangement and attributes of text.  Formatters can
manipulate structure and attributes to change the text layout and
appearance.

To use a formatter with a text widget, we must use a different
constructor function, \fw{text\-Widget}:

\begin{haskellcode}
 t <- textWidget wrap "foobar"
\end{haskellcode}

When a text widget's contents are updated, the text is automatically
broken up into tokens (see Section \ref{sec:updatingText}).  It is
these tokens on which formatters operate.

The \fw{Text} module provides two formatters: \fw{wrap} and
\fw{highlight}.  \fw{wrap} wraps the text to fit into the
\fw{DisplayRegion} available at rendering time, so this will end up
doing the right thing depending on the parent widget of the
\fw{FormattedText} widget.  \fw{highlight} accepts a regular
expression\footnote{Any instance of \fw{RegexLike} is acceptable.} to
match text for highlighting.  To construct a highlighting formatter,
we must provide the regular expression used to match strings as well
as the attribute that should be applied to the matches:\footnote{Since
  formatters operate on individual tokens, the \fw{highlight}
  formatter applies its regular expression to each token individually,
  so it will only ever match sequences of characters in each token
  rather than matching more than one token.  You can certainly write
  your own formatter that considers more than one token at a time,
  though.}

Here is an example using \fw{highlight} with the \fw{Regex} type from
the \fw{regex-pcre} package:

\begin{haskellcode}
 let doHighlight sz t = do
   Right r <- compile (compUngreedy .|. compMultiline) execBlank "<.*>"
   highlight r (fgColor bright_green) sz t
 t <- textWidget doHighlight "foo <bar> baz"
\end{haskellcode}

Formatters can be composed with the \fw{\&.\&} operator.  This
operator constructs a new formatter which will apply the operand
formatters in the specified order.  We can use this operator to
compose the built-in formatters on a single \fw{FormattedText} widget:

\begin{haskellcode}
 t <- textWidget (doHighlight &.& wrap) "Foo <bar> baz"
\end{haskellcode}

For detailed information on the token types on which the formatters
operate, see the \fw{Text.Trans.Tokenize} module.

\subsubsection{Growth Policy}

\fw{FormattedText} widgets do not grow horizontally or vertically.
{'fraction_non_alphanumeric': 0.07940314415134558, 'fraction_numerical': 0.0021316280309086064, 'mean_word_length': 4.3128096249115355, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2100300', 'n_tokens_mistral': 2143, 'n_tokens_neox': 2063, 'n_words': 966}