core-text- A rope type based on a finger tree over UTF-8 fragments
Safe HaskellNone



Useful tools for working with Ropes. Support for pretty printing, multi-line strings, and...


Pretty printing

class Render α where Source #

Types which can be rendered "prettily", that is, formatted by a pretty printer and embossed with beautiful ANSI colours when printed to the terminal.

Use render to build text object for later use or < Control.Program.Logging>'s < writeR> if you're writing directly to console now.

Associated Types

type Token α :: Type Source #

Which type are the annotations of your Doc going to be expressed in?


colourize :: Token α -> AnsiColour Source #

Convert semantic tokens to specific ANSI escape tokens

highlight :: α -> Doc (Token α) Source #

Arrange your type as a Doc ann, annotated with your semantic tokens.


Instances details
Render Char Source # 
Instance details

Defined in Core.Text.Utilities

Associated Types

type Token Char Source #

Render String Source # 
Instance details

Defined in Core.Text.Utilities

Associated Types

type Token String Source #

Render Text Source # 
Instance details

Defined in Core.Text.Utilities

Associated Types

type Token Text Source #

Render Bytes Source # 
Instance details

Defined in Core.Text.Utilities

Associated Types

type Token Bytes Source #

Render Rope Source # 
Instance details

Defined in Core.Text.Utilities

Associated Types

type Token Rope Source #

Render a => Render [a] Source # 
Instance details

Defined in Core.Text.Utilities

Associated Types

type Token [a] Source #


colourize :: Token [a] -> AnsiColour Source #

highlight :: [a] -> Doc (Token [a]) Source #

render :: Render α => Int -> α -> Rope Source #

Given an object of a type with a Render instance, transform it into a Rope saturated with ANSI escape codes representing syntax highlighting or similar colouring, wrapping at the specified width.

The obvious expectation is that the next thing you're going to do is send the Rope to console with:

    write (render 80 thing)

However, the better thing to do is to instead use:

    writeR thing

which is able to pretty print the document text respecting the available width of the terminal.

renderNoAnsi :: Render α => Int -> α -> Rope Source #

Having gone to all the trouble to colourize your rendered types... sometimes you don't want that. This function is like render, but removes all the ANSI escape codes so it comes outformatted but as plain black & white text.


indefinite :: Rope -> Rope Source #

Render "a" or "an" in front of a word depending on English's idea of whether it's a vowel or not.

oxford :: [Rope] -> Rope Source #

Given a list of items (one word per Rope in the list) enumerate them with commas and an Oxford comma before the last item. As you'd expect:

λ> oxford ["one", "two", "three"]
"one, two, and three"

Because English is ridiculous, however, and we can't have nice things, two items are a special case:

λ> oxford ["four", "five"]
"four and five"

Sadly if there is only one item you don't get an Oxford comma, either:

λ> oxford ["six"]
λ> oxford []

breakRope :: (Char -> Bool) -> Rope -> (Rope, Rope) Source #

Given a piece of Rope and a predicate, break the text into two pieces at the first site where that predicate returns True.

Since: 0.3.7

breakWords :: Rope -> [Rope] Source #

Split a passage of text into a list of words. A line is broken wherever there is one or more whitespace characters, as defined by Data.Char's isSpace.


λ> breakWords "This is a test"
λ> breakWords ("St" <> "op and " <> "go left")
λ> breakWords emptyRope

breakLines :: Rope -> [Rope] Source #

Split a paragraph of text into a list of its individual lines. The paragraph will be broken wherever there is a 'n' character.

Blank lines will be preserved. Note that as a special case you do not get a blank entry at the end of the a list of newline terminated strings.

λ> breakLines "Hello\n\nWorld\n"

breakPieces :: (Char -> Bool) -> Rope -> [Rope] Source #

Break a Rope into pieces whereever the given predicate function returns True. If found, that character will not be included on either side. Empty runs, however, *will* be preserved.

isNewline :: Char -> Bool Source #

Predicate testing whether a character is a newline. After isSpace et al in Data.Char.

wrap :: Int -> Rope -> Rope Source #

Often the input text represents a paragraph, but does not have any internal newlines (representing word wrapping). This function takes a line of text and inserts newlines to simulate such folding, keeping the line under the supplied maximum width.

A single word that is excessively long will be included as-is on its own line (that line will exceed the desired maxium width).

Any trailing newlines will be removed.

calculatePositionEnd :: Rope -> (Int, Int) Source #

Calculate the line number and column number of a Rope (interpreting it as if is a block of text in a file). By the convention observed by all leading brands of text editor, lines and columns are 1 origin, so an empty Rope is position (1,1).

leftPadWith :: Char -> Int -> Rope -> Rope Source #

Pad a piece of text on the left with a specified character to the desired width. This function is named in homage to the famous result from Computer Science known as leftPad which has a glorious place in the history of the world-wide web.

rightPadWith :: Char -> Int -> Rope -> Rope Source #

Right pad a text with the specified character.

Multi-line strings

quote :: QuasiQuoter Source #

Multi-line string literals.

To use these you need to enable the QuasiQuotes language extension in your source file:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}

you are then able to easily write a string stretching over several lines.

How best to formatting multi-line string literal within your source code is an aesthetic judgement. Sometimes you don't care about the whitespace leading a passage (8 spaces in this example):

    let message = [quote|
        This is a test of the Emergency Broadcast System. Do not be
        alarmed. If this were a real emergency, someone would have tweeted
        about it by now.

because you are feeding it into a Doc for pretty printing and know the renderer will convert the whole text into a single line and then re-flow it. Other times you will want to have the string as is, literally:

    let poem = [quote|
If the sun
        in the
you     drank
    too much
                last week.

Leading whitespace from the first line and trailing whitespace from the last line will be trimmed, so this:

    let value = [quote|

is translated to:

    let value = fromString "Hello\n"

without the leading newline or trailing four spaces. Note that as string literals they are presented to your code with fromString :: String -> α so any type with an IsString instance (as Rope has) can be constructed from a multi-line [quote| ... |] literal.


intoDocA :: α -> Doc (Token α) Source #

Deprecated: methodintoDocA has been renamed highlight; implement that instead.

Nothing should be invoking intoDocA.

AnsiColour and colour constants moved to this module.