Textwrap (Textwrap v0.1.0) View Source

Textwrap provides a set of functions for wrapping, indenting, and dedenting text. It wraps the Rust textwrap crate.

Wrapping

Use wrap/2 to turn a String into a list of Strings each no more than width characters long.

iex> Textwrap.wrap("foo bar baz", 3)
["foo", "bar", "baz"]

iex> Textwrap.wrap("foo bar baz", 7)
["foo bar", "baz"]

fill/2 is like wrap/2, except that it retuns the wrapped text as a single String.

iex> Textwrap.fill("foo bar baz", 3)
"foo\nbar\nbaz"

iex> Textwrap.fill("foo bar baz", 7)
"foo bar\nbaz"

Both wrap/2 and fill/2 can either take the width to wrap too as their second argument, or take a keyword list including a :width key and any number of other options. See the docs for wrap/2 for details.

Displayed Width vs Byte Width

Textwrap wraps text based on measured display width, not simply counting bytes. For ascii text this gives exactly the same result, but many non-ASCII characters take up more than one byte in the UTF-8 encoding.

See the documentation of the textwrap crate for more details.

Terminal Width

The width passed to wrap/2 or fill/2 can either by a positive integer, or the atom :termwidth. When standard output is connected to a terminal, passing :termwidth will wrap the text to the width of the terminal. Otherwise, it will use a width of 80 characters as a fallback.

Indenting and Dedenting

Use indent/2 and dedent/1 to indent and dedent text:

iex> Textwrap.indent("hello\nworld\n", "  ")
"  hello\n  world\n"

iex> Textwrap.dedent("  hello\n  world\n")
"hello\nworld\n"

Link to this section Summary

Functions

Removes as much common leading whitespace as possible from each line.

Fills text to the given width.

Adds a given prefix to each non-empty line.

Wraps text to the given width.

Link to this section Types

Specs

wrap_algorithm() :: :first_fit | :optimal_fit

Specs

wrap_opt() ::
  {:width, pos_integer() | :termwidth}
  | {:break_words, boolean()}
  | {:initial_indent, String.t()}
  | {:splitter, nil | :en_us | false}
  | {:subsequent_indent, String.t()}
  | {:wrap_algorithm, wrap_algorithm()}

Specs

wrap_opts() :: pos_integer() | :termwidth | [wrap_opt()]

Link to this section Functions

Specs

dedent(text :: String.t()) :: String.t()

Removes as much common leading whitespace as possible from each line.

Each non-empty line has an equal amount of whitespace removed from its start.

Empty lines (containing only whitespace) are normalized to a single \n, with no other whitespace on the line.

Examples:

iex> Textwrap.dedent("    hello world")
"hello world"

iex> Textwrap.dedent("
...>  foo
...>    bar
...>  baz
...>      ")
"\nfoo\n  bar\nbaz\n"
Link to this function

fill(text, width_or_opts)

View Source

Specs

fill(text :: String.t(), opts :: wrap_opts()) :: String.t()

Fills text to the given width.

The result is a String, with lines seperated by newline. The wrap/2 function does the same thing, except that it returns a list of Strings, one for each line.

See the docs for wrap/2 for details about the options it takes.

Examples

iex> Textwrap.fill("hello world", 5)
"hello\nworld"

iex> Textwrap.fill("hello world", width: 5)
"hello\nworld"

iex> Textwrap.fill("Antidisestablishmentarianism", width: 10)
"Antidisest\nablishment\narianism"

iex> Textwrap.fill("Antidisestablishmentarianism", width: 10, break_words: false)
"Antidisestablishmentarianism"

iex> Textwrap.fill("Antidisestablishmentarianism", width: 10, splitter: :en_us)
"Antidis-\nestablish-\nmentarian-\nism"

iex> Textwrap.fill("foo bar baz",
...>      width: 5,
...>      initial_indent: "> ",
...>      subsequent_indent: "  ")
"> foo\n  bar\n  baz"

iex> Textwrap.fill("Lorem ipsum dolor sit amet, consectetur adipisicing elit",
...>      width: 25,
...>      wrap_algorithm: :optimal_fit)
"Lorem ipsum dolor\nsit amet, consectetur\nadipisicing elit"

iex> Textwrap.fill("Lorem ipsum dolor sit amet, consectetur adipisicing elit",
...>      width: 25,
...>      wrap_algorithm: :first_fit)
"Lorem ipsum dolor sit\namet, consectetur\nadipisicing elit"

Specs

indent(text :: String.t(), prefix :: String.t()) :: String.t()

Adds a given prefix to each non-empty line.

Empty lines (containing only whitespace) are normalized to a single \n, and not indented.

Any leading and trailing whitespace on non-empty lines is left unchanged.

Examples:

iex> Textwrap.indent("hello world", ">")
">hello world"

iex> Textwrap.indent("foo\nbar\nbaz\n", "  ")
"  foo\n  bar\n  baz\n"
Link to this function

wrap(text, width_or_opts)

View Source

Specs

wrap(text :: String.t(), opts :: wrap_opts()) :: [String.t()]

Wraps text to the given width.

wrap/2 returns a list of Strings, each of no more than width charecters.

Options can be either passed as a keyword list (which must include the key :width), or, if using no options other than :width, the width can be passed on its own as the second argument.

width can either by a positive integer or the atom :termwidth. See the module docs on :termwidth for more details.

Options

  • :width — the width to wrap at, a positive integer.
  • :break_words — allow long words to be broken, if they won't fit on a single line. Setting this to false may cause some lines to be longer than :width.
  • :inital_indent — will be added as a prefix to the first line of the result.
  • :subsequent_indent — will be added as a prefix to each line other than the first line of the result.
  • :splitter — when set to false, hyphens within words won't be treated specially as a place to split words. When set to :en_us, a language-aware hyphenation system will be used to try to break words in appropriate places.
  • :wrap_algorithm — by default, or when set to :optimal_fit, wrap/2 will do its best to balance the gaps left at the ends of lines. When set to :first_fit, a simpler greedy algorithm is used instead. See the docs in the textwrap crate for more details.

Examples

iex> Textwrap.wrap("hello world", 5)
["hello", "world"]

iex> Textwrap.wrap("hello world", width: 5)
["hello", "world"]

iex> Textwrap.wrap("Antidisestablishmentarianism", width: 10)
["Antidisest", "ablishment", "arianism"]

iex> Textwrap.wrap("Antidisestablishmentarianism", width: 10, break_words: false)
["Antidisestablishmentarianism"]

iex> Textwrap.wrap("Antidisestablishmentarianism", width: 10, splitter: :en_us)
["Antidis-", "establish-", "mentarian-", "ism"]

iex> Textwrap.wrap("foo bar baz",
...>      width: 5,
...>      initial_indent: "> ",
...>      subsequent_indent: "  ")
["> foo", "  bar", "  baz"]

iex> Textwrap.wrap("Lorem ipsum dolor sit amet, consectetur adipisicing elit",
...>      width: 25,
...>      wrap_algorithm: :optimal_fit)
["Lorem ipsum dolor", "sit amet, consectetur", "adipisicing elit"]

iex> Textwrap.wrap("Lorem ipsum dolor sit amet, consectetur adipisicing elit",
...>      width: 25,
...>      wrap_algorithm: :first_fit)
["Lorem ipsum dolor sit", "amet, consectetur", "adipisicing elit"]