Skip to main content

trimmargin Logo

trimmargin ✂️📏

Kotlin-style trimMargin and friends for Python — with a tiny CLI

PyPI Python Versions PyPI Status License: MIT Downloads


Features

  • 🔄 Normalizes line endings to \n
  • 🧼 Drops first/last blank lines (edges only, not interior)
  • 🧲 trim_margin() strips leading whitespace + a margin prefix (default |)
  • 🔧 replace_indent_by_margin() like Kotlin’s, with a custom replacement indent
  • 🪄 trim_indent() / replace_indent() built on textwrap.dedent/indent
  • ➕ prepend_indent() behaves like Kotlin (blank-line quirk covered)

Installation

# uv (recommended)
uv pip install trimmargin

# or pip
pip install trimmargin

Quick Start

from trimmargin import trim_margin, replace_indent_by_margin

text = """
    |hello
    |world
"""

print(trim_margin(text))
# hello
# world

print(replace_indent_by_margin(text, new_indent=">>> "))
# >>> hello
# >>> world

Behavior Notes

  • If a line’s first non-whitespace char starts the margin prefix, both the leading whitespace and the prefix are removed; other lines are unchanged.
  • Only the first and last blank lines are dropped.
  • Input may use \r\n, \n, or \r; output uses \n.

CLI Usage 🚀

The trimmargin command reads a file or stdin and writes to stdout.

# default: trim-margin on stdin using prefix "|"
trimmargin < input.txt

# file input
trimmargin input.txt

# modes
trimmargin --mode replace-by-margin --new-indent ">>> " input.txt
trimmargin --mode trim-indent < input.txt
trimmargin --mode replace-indent --new-indent "  " < input.txt
trimmargin --mode prepend --indent ">> "

# change margin prefix
trimmargin --prefix "§" < input.txt

# version
trimmargin --version

Modes

  • trim-margin (default): remove leading whitespace + prefix

  • replace-by-margin: same detection as above, then add new-indent

  • trim-indent: remove common indent via textwrap.dedent

  • replace-indent: dedent then indent non-blank lines with new-indent

  • prepend: prepend indent to non-blank lines; blank-line quirk matches Kotlin:

    • if blank and len(line) < len(indent): line becomes exactly indent
    • else: leave blank line unchanged

Development (uv) 🧑‍💻

# setup
uv sync --extra dev

# tests
uv run pytest

# lint & types
uv run ruff check .
uv run mypy src

# format
uv run ruff format .

# build & publish
uv build
uv publish

Why This Exists ❓

textwrap.dedent/indent are great, but Kotlin’s margin-aware trimming is handy for multiline literals embedded in code and docs.

Metadata

Release files for trimmargin 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trimmargin 1.0.0
File Size Uploaded Provenance Actions
trimmargin-1.0.0.tar.gz 5.1 kB Without provenance Details for trimmargin-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for trimmargin 1.0.0
File Interpreter ABI Platform Actions
trimmargin-1.0.0-py3-none-any.whl Python 3 none any Details for trimmargin-1.0.0-py3-none-any.whl

Total release size: 11.9 kB

Release files / trimmargin-1.0.0.tar.gz

Download URL trimmargin-1.0.0.tar.gz
Size 5.1 kB
Tags Source
SHA-256 checksum
How to use checksums
55c6cf2a6de1f4bfc347a0d1ed781cdea805fca6a8d7c14e1c4699876a68d2b3
BLAKE2b-256 checksum
How to use checksums
694d263ed38995448d89f3a7d655fa032216b043229c8c313afef132df0bf61d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.5.2

Release files / trimmargin-1.0.0-py3-none-any.whl

Download URL trimmargin-1.0.0-py3-none-any.whl
Size 6.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1b16c9243e015b0347edddd2b414fd02ba28cf7c07341923bd2035708e64f28f
BLAKE2b-256 checksum
How to use checksums
26caeff650b3b19b3bb595e277717d0043bd89a85205d6362d87a9bc22d6deac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.5.2

Security for trimmargin 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page