reflex-vty-0.1.2.0: Reflex FRP host and widgets for vty applications

Data.Text.Zipper

Description

TextZipper is designed to be help manipulate the contents of a text input field. It keeps track of the logical lines of text (i.e., lines separated by user-entered newlines) and the current cursor position. Several functions are defined in this module to navigate and edit the TextZipper from the cursor position.

TextZippers can be converted into DisplayLines, which describe how the contents of the zipper will be displayed when wrapped to fit within a container of a certain width. It also provides some convenience facilities for converting interactions with the rendered DisplayLines back into manipulations of the underlying TextZipper.

Synopsis

# Documentation

A zipper of the logical text input contents (the "document"). The lines before the line containing the cursor are stored in reverse order. The cursor is logically between the "before" and "after" text. A "logical" line of input is a line of input up until a user-entered newline character (as compared to a "display" line, which is wrapped to fit within a given viewport width).

Constructors

 TextZipper Fields
Instances
 Source # Instance detailsDefined in Data.Text.Zipper MethodsshowList :: [TextZipper] -> ShowS # Source # Instance detailsDefined in Data.Text.Zipper Methods

mapZipper :: (Char -> Char) -> TextZipper -> TextZipper Source #

Map a replacement function over the characters in a TextZipper

Move the cursor left one character, if possible

Move the cursor left by the given number of characters, or, if the document isn't long enough, to the beginning of the document

Move the cursor right one character, if possible

Move the character right by the given number of characters, or, if the document isn't long enough, to the end of the document

Move the cursor up one logical line, if possible

Move the cursor down one logical line, if possible

Move the cursor up by the given number of lines

Move the cursor down by the given number of lines

Move the cursor to the beginning of the current logical line

Move the cursor to the end of the current logical line

Move the cursor to the top of the document

Insert a character at the current cursor position

Insert text at the current cursor position

Delete the character to the left of the cursor

Delete the character under/to the right of the cursor

Delete a word to the left of the cursor. Deletes all whitespace until it finds a non-whitespace character, and then deletes contiguous non-whitespace characters.

Insert up to n spaces to get to the next logical column that is a multiple of n

The plain text contents of the zipper

The empty zipper

Constructs a zipper with the given contents. The cursor is placed after the contents.

data Span tag Source #

A span of text tagged with some metadata that makes up part of a display line.

Constructors

 Span tag Text
Instances
 Show tag => Show (Span tag) Source # Instance detailsDefined in Data.Text.Zipper MethodsshowsPrec :: Int -> Span tag -> ShowS #show :: Span tag -> String #showList :: [Span tag] -> ShowS #

data DisplayLines tag Source #

Information about the document as it is displayed (i.e., post-wrapping)

Constructors

 DisplayLines Fields_displayLines_spans :: [[Span tag]] _displayLines_offsetMap :: Map Int Int _displayLines_cursorY :: Int
Instances
 Show tag => Show (DisplayLines tag) Source # Instance detailsDefined in Data.Text.Zipper MethodsshowsPrec :: Int -> DisplayLines tag -> ShowS #show :: DisplayLines tag -> String #showList :: [DisplayLines tag] -> ShowS #

Arguments

 :: Int Width, used for wrapping -> tag Metadata for normal characters -> tag Metadata for the cursor -> TextZipper The text input contents and cursor state -> DisplayLines tag

Given a width and a TextZipper, produce a list of display lines (i.e., lines of wrapped text) with special attributes applied to certain segments (e.g., the cursor). Additionally, produce the current y-coordinate of the cursor and a mapping from display line number to text offset

Arguments

 :: Int Maximum width -> Int Offset for first line -> Text Text to be wrapped -> [Text]

Wraps a logical line of text to fit within the given width. The first wrapped line is offset by the number of columns provided. Subsequent wrapped lines are not.

splitAtWidth :: Int -> Text -> (Text, Text) Source #

Split a Text at the given column index. For example

splitAtWidth 3 "ᄀabc" == ("ᄀa", "bc")

because the first character has a width of two (see charWidth for more on that).

Takes the given number of columns of characters. For example

takeWidth 3 "ᄀabc" == "ᄀa"

because the first character has a width of 2 (see charWidth for more on that). This function will not take a character if its width exceeds the width it seeks to take.

Drops the given number of columns of characters. For example

dropWidth 2 "ᄀabc" == "abc"

because the first character has a width of 2 (see charWidth for more on that). This function will not drop a character if its width exceeds the width it seeks to drop.

Get the display width of a Char. "Full width" and "wide" characters take two columns and everything else takes a single column. See https://www.unicode.org/reports/tr11/ for more information.

Arguments

 :: [[Text]] The outer list represents logical lines, and the inner list represents the display lines into which the logical line has been wrapped -> Map Int Int A map from the index (row) of display line to the text offset from the beginning of the document to the first character of the display line

For a given set of wrapped logical lines, computes a map from display line index to text offset in the original text. This is used to help determine how interactions with the displayed text map back to the original text. For example, given the document "AA\nBBB\nCCCCCCCC\n" wrapped to 5 columns, this function will compute the offset in the original document of each character in column 1:

  AA...      (0, 0)
BBB..      (1, 3)
CCCCC      (2, 7)  -- (this line wraps to the next row)
CCC..      (3, 12)
.....      (4, 16)

Move the cursor of the given TextZipper to the logical position indicated by the given display line coordinates, using the provided DisplayLines information. If the x coordinate is beyond the end of a line, the cursor is moved to the end of the line.

spansWidth :: [Span tag] -> Int Source #

Get the width of the text in a set of Spans, taking into account unicode character widths

spansLength :: [Span tag] -> Int Source #

Get the length (number of characters) of the text in a set of Spans

Compute the width of some Text, taking into account fullwidth unicode forms.

Compute the width of a stream of characters, taking into account fullwidth unicode forms.