Teaching BBEdit to Know Soft Wrap setting for OCR Text Files

I recently ran into a problem while processing a large batch of OCR text files.

The workflow was simple: scanned PDFs → OCR → text files → BBEdit search. The OCR output was fine structurally, with one line per paragraph, but reading it in BBEdit was unpleasant. Long lines ran off the right side of the window. Search still worked, but visual scanning was harder than it should be.

What I wanted was simple. Every OCR text file should open in BBEdit with Soft Wrap enabled.

BBEdit does not provide a setting for this at the file level. There is no xattr or modeline for it.

Where BBEdit stores document state

BBEdit stores per-file state in a property list here:

~/Library/Containers/com.barebones.bbedit/Data/Library/BBEdit/Document State.plist

This file acts like a database. Each entry is keyed by file path, and contains a dictionary of state data for that file.

The setting I cared about is:

<key>SoftWrapText</key>
<true/>

It lives inside:

StateEntries_v1
    └── file path
        └── BBEditStateData

BBEdit uses this structure to store editor state per file.

Path matching matters

My first attempt did not work correctly.

I had entries like:

1981/08_rainbow.txt

But BBEdit was using full paths like:

/Volumes/ARCHIVE/Rainbows/1981/08_rainbow.txt

BBEdit matches state strictly by path. If the key does not match exactly, it is ignored.

The fix was to always normalize paths before writing them.

Files on external volumes stay absolute. Files inside the home directory can use ~/.

In Python, this is handled with:

path = path.resolve()

Automating Soft Wrap for many files

Once the structure was correct, I wrote a script that:

  • finds all .txt files recursively
  • computes the correct BBEdit key for each file
  • sets SoftWrapText = true
  • preserves existing BBEdit metadata

The key function is:

def bbedit_key_for(path: Path) -> str:
    path = path.resolve()

    try:
        rel = path.relative_to(Path.home())
        return f"~/{rel}"
    except ValueError:
        return str(path)

Everything else is plist editing.

Result

After running this across the OCR archive:

  • all text files open with wrapping enabled
  • BBEdit search still works normally
  • no changes to the original files
  • no need to insert line breaks into OCR output

The workflow is now easier to read without affecting how search behaves.

What this is doing

BBEdit stores per-file editor state in a plist that behaves like a small database keyed by file path.

Once that is visible, it becomes possible to automate editor behavior for large sets of files instead of adjusting settings manually.

This can be extended beyond Soft Wrap to other per-file state BBEdit tracks.