Metadata-Version: 2.4
Name: pet-doc
Version: 1.0.2
Summary: Program Enhanced Text — documentation automation tool
Project-URL: Homepage, https://github.com/verhasp/pet
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: automation,documentation,markdown,template
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Documentation
Classifier: Topic :: Text Processing :: Markup :: Markdown
Requires-Python: >=3.11
Requires-Dist: pyyaml
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Description-Content-Type: text/markdown


# 🐾 PET — Program Enhanced Text

> **Write docs once. Automate the rest. Never copy-paste again.**

[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org)
[![License](https://img.shields.io/badge/license-Apache%202.0-green)](LICENSE)
[![Version](https://img.shields.io/badge/version-1.0.2-orange)](pyproject.toml)

---

PET turns your documentation into a **living document**.
Instead of manually copying version numbers, pasting code samples, and updating
chapter headings by hand, you write a `.md.pet` template and let PET generate
the final Markdown. When your source changes, regenerate — done.

```bash
pet  README.md.pet  README.md
```

---

> **Not just Markdown.** PET works with any text-based format — AsciiDoc,
> reStructuredText, LaTeX, HTML, plain text, or anything else. The template
> extension and output format are entirely up to you. Markdown is the most
> common use case, which is why the examples here use it.

---

# 1 The Idea in 30 Seconds

A `.md.pet` file is regular Markdown with Python code blocks between
`{%` and `%}`. PET executes the blocks and splices their
output into the document.

**Template** (`docs.md.pet`):

```markdown
{%
use('number')
use('snippet')
n = number(fmt="{:3d}  ")
src = snippet("src")
%}

The core loop:

{% doc | n(src('main_loop')) %}
```

**Output** (`docs.md`):

```markdown
The core loop:

  1  for item in queue:
  2      process(item)
  3      log(item)
```

PET replaces every `{% ... %}` block with whatever that Python
code prints. Everything else passes through untouched.

---

# 2 Installation

```bash
pip install pet-doc
```

Initialise a project (copies the macro library into `.pet/`):

```bash
cd my-project
pet init                  # first-time setup
pet init                  # safe to re-run — regenerates if macros unchanged, skips if you've edited them
pet init -f               # force regeneration regardless of local edits
pet init for_claude       # also installs the pet skill into Claude Code (.claude/)
```

Process a template once, or watch it for changes:

```bash
pet  my-doc.md.pet  my-doc.md          # one-shot
pet watch my-doc.md.pet my-doc.md      # live reload on every save
```

---

# 3 Built-in Macro Library

### Text & Structure

| Macro | What it does |
|-------|-------------|
| `chapter(header_prefix="#", sep=" ")` | Hierarchical section counter — `# 1`, `## 1.1`, `### 1.1.1` |
| `number(start=1, step=1, fmt="{} ")` | Prefix each line of a text block with a sequential number |
| `include(filename)` | Read any file and return its content as a string |
| `snippet(directory)` | Scan source files for named `snippet` / `end snippet` markers |
| `dedent(text)` | Strip common leading indentation from included code |

### Data Readers

All data macros expose `get("dot.separated.path")` for deep value access.
Lists support integer indices: `get("dependencies.0.name")`.

| Macro | Format |
|-------|--------|
| `toml(file)` | TOML — great for `pyproject.toml`, config files |
| `yaml(file)` | YAML — nested keys, lists, indexed access |
| `json(file)` | JSON — identical API to `yaml` |
| `xml(file)` | XML — xpath queries, attribute access via `attr()` |
| `properties(file)` | Java `.properties` — flat `key=value`, dotted keys preserved |
| `env(file)` | `.env` files — strips surrounding quotes, skips comments |

### Pipelines

`pipe` is an identity transformer. Compose steps with `|`:

```python
use('pipe')
use('dedent')
use('number')

n      = number(fmt="{:3d}  ")
clean  = pipe | dedent | n   # dedent first, then add line numbers

doc | clean(include("src/core.py"))
```

Apply a transformation **line by line** with `.on_lines()`:

```python
shout = pipe | str.upper
doc | shout.on_lines()(include("words.txt"))
```

---

# 4 Worked Example — This README

This very document is generated by PET 1.0.2.
The version badge above is not hardcoded — it is read live from `pyproject.toml`:

```python
 1 | use('data/toml')
 2 | proj = toml("pyproject.toml")
 3 | VERSION = proj.get('project.version')
```

The section headings are auto-numbered by `chapter`:

```python
 4 | ch = chapter()
 5 | # becomes  ->  # 1 The Idea in 30 Seconds
 6 | # becomes  ->  # 2 Installation
 7 | # etc.
```

Change the order, add a section, remove one — the numbers update on the next
`pet README.md.pet README.md`.

---

# 5 Why PET?

Documentation rots. Code evolves, but the docs that reference it often don't.
Copy-pasted version numbers fall behind. Pasted code samples go stale.
Chapter numbers break the moment you reorder sections.

PET's answer is deliberately small:

- **No new language** — your macros are plain Python classes
- **No build framework** — one command, one output file
- **No lock-in** — the output is standard Markdown; stop using PET any time
- **Self-documenting** — the template *is* the documentation intent

If information already exists somewhere in your project, humans shouldn't
maintain a second copy of it. PET makes the automated copy the only copy.

For the full theory — single-source-of-truth, consistency checks as document
unit tests, and why correct docs matter more than ever in the age of LLM RAG —
see **[RATIONALE.md](RATIONALE.md)**.

To learn how to write your own macros, with every built-in macro explained
pattern by pattern, see **[MACROGUIDE.md](MACROGUIDE.md)**.

---

*Generated from `README.md.pet` by PET 1.0.2 · `pet README.md.pet README.md`*
