Skip to content
/ para Public

Paragraph compressor, line wrapper. For use with acme / sam

License

Notifications You must be signed in to change notification settings

jsilvela/para

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

para

A simple command-line utility to wrap text to a given number of columns.
Meant for wrapping of text in Sam or Acme, or any other editors which don't do their own wrapping/compacting.

para wraps text to a given column, filling each line as much as possible, to form compact paragraphs. When compacting, it respects full stops and paragraph breaks. It also respects Markdown headers and list items.

Usage

para [wrapColumn (optional)]

If the optional number is not provided, the default width is 80.

para takes input from stdin, and outputs to stdout; this is so that it can be used as a piped command in Acme or Sam.

Building / testing

Clone the repo, then.

cd cloned-repo
go test
go build
go install

Note that depending on your Go environment, you may need to execute the go install with privileges.

How it works

para fills two goals: wrapping and compacting.

Wrapping on its own is easy. We keep a running count of the length since the last newline, and when we exceed the max width, we change the last whitespace into a newline:

word1 word2 word3 … wordOverflows wordNext …

Would become:

word1 word2 word3 …
wordOverflows wordNext …`

But if we want to compact paragraphs, we need some interaction between lines of input.

Imagine that after wrapping a given input line, we get the following.

word word word word word word word word word word word word
word word word word word word word word word word word word
word

We would want the next input line to continue filling the same paragraph.

word word word word word word word word word word word word
word word word word word word word word word word word word
word newLineWord newLineWord newLineWord newLineWord …

This means that when wrapping a line of input:

  1. we don't necessarily want to "close" the paragraph with a newline
  2. we may want to append to an un-closed paragraph seen previously

To fill these needs, we keep track of the carry between lines of input. c.f. the signature of the central function:

wrapLine(line string, carry int) (wrapped string, newCarry int)

With this signature in place, the code becomes clear. Special care needs to be taken with:

  • paragraph breaks (i.e. empty lines)
  • full stops (i.e. lines of input ending with ".\n")
  • Markdown sections
  • Markdown lists

These should be respected. Compaction should be skipped for them. We achieve this by flushing the un-closed running text:

flushRunningText := func() {
    if carry > 0 {
        writer.WriteString("\n")
        carry = 0
    }
}

About

Paragraph compressor, line wrapper. For use with acme / sam

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages