Skip to content
/ reflow Public

A collection of (ANSI-sequence aware) text reflow operations & algorithms

License

Notifications You must be signed in to change notification settings

muesli/reflow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

83f6379 · Mar 16, 2023

History

90 Commits
Mar 16, 2023
Nov 26, 2020
Oct 31, 2020
Oct 20, 2020
Oct 20, 2020
Oct 21, 2020
May 2, 2021
Oct 24, 2020
Jun 12, 2021
Nov 27, 2019
Jul 7, 2021
Nov 27, 2019
Jul 7, 2021
Sep 22, 2022
Sep 22, 2022
Nov 28, 2019

Repository files navigation

reflow

Latest Release Build Status Coverage Status Go ReportCard GoDoc

A collection of ANSI-aware methods and io.Writers helping you to transform blocks of text. This means you can still style your terminal output with ANSI escape sequences without them affecting the reflow operations & algorithms.

Word-Wrapping

The wordwrap package lets you word-wrap strings or entire blocks of text.

import "github.com/muesli/reflow/wordwrap"

s := wordwrap.String("Hello World!", 5)
fmt.Println(s)

Result:

Hello
World!

The word-wrapping Writer is compatible with the io.Writer / io.WriteCloser interfaces:

f := wordwrap.NewWriter(limit)
f.Write(b)
f.Close()

fmt.Println(f.String())

Customize word-wrapping behavior:

f := wordwrap.NewWriter(limit)
f.Breakpoints = []rune{':', ','}
f.Newline = []rune{'\r'}

Unconditional Wrapping

The wrap package lets you unconditionally wrap strings or entire blocks of text.

import "github.com/muesli/reflow/wrap"

s := wrap.String("Hello World!", 7)
fmt.Println(s)

Result:

Hello W
orld!

The unconditional wrapping Writer is compatible with the io.Writer interfaces:

f := wrap.NewWriter(limit)
f.Write(b)

fmt.Println(f.String())

Customize word-wrapping behavior:

f := wrap.NewWriter(limit)
f.Newline = []rune{'\r'}
f.KeepNewlines = false
f.PreserveSpace = true
f.TabWidth = 2

Tip: This wrapping method can be used in conjunction with word-wrapping when word-wrapping is preferred but a line limit has to be enforced:

wrapped := wrap.String(wordwrap.String("Just an example", 5), 5)
fmt.Println(wrapped)

Result:

Just
an
examp
le

ANSI Example

s := wordwrap.String("I really \x1B[38;2;249;38;114mlove\x1B[0m Go!", 8)
fmt.Println(s)

Result:

ANSI Example Output

Indentation

The indent package lets you indent strings or entire blocks of text.

import "github.com/muesli/reflow/indent"

s := indent.String("Hello World!", 4)
fmt.Println(s)

Result:

    Hello World!

There is also an indenting Writer, which is compatible with the io.Writer interface:

// indent uses spaces per default:
f := indent.NewWriter(width, nil)

// but you can also use a custom indentation function:
f = indent.NewWriter(width, func(w io.Writer) {
    w.Write([]byte("."))
})

f.Write(b)
f.Close()

fmt.Println(f.String())

Dedentation

The dedent package lets you dedent strings or entire blocks of text.

import "github.com/muesli/reflow/dedent"

input := `    Hello World!
  Hello World!
`

s := dedent.String(input)
fmt.Println(s)

Result:

  Hello World!
Hello World!

Padding

The padding package lets you pad strings or entire blocks of text.

import "github.com/muesli/reflow/padding"

s := padding.String("Hello", 8)
fmt.Println(s)

Result: Hello___ (the underlined portion represents 3 spaces)

There is also a padding Writer, which is compatible with the io.WriteCloser interface:

// padding uses spaces per default:
f := padding.NewWriter(width, nil)

// but you can also use a custom padding function:
f = padding.NewWriter(width, func(w io.Writer) {
    w.Write([]byte("."))
})

f.Write(b)
f.Close()

fmt.Println(f.String())