Full Code of mfontanini/presenterm for AI

master 952061abec94 cached
155 files
1.1 MB
263.3k tokens
1794 symbols
1 requests
Download .txt
Showing preview only (1,130K chars total). Download the full file or copy to clipboard to get everything.
Repository: mfontanini/presenterm
Branch: master
Commit: 952061abec94
Files: 155
Total size: 1.1 MB

Directory structure:
gitextract_hsyzsbc9/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── docs.yaml
│       ├── merge.yaml
│       ├── nightly.yaml
│       └── release.yaml
├── .gitignore
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── bat/
│   ├── acknowledgements.txt
│   ├── bat.git-hash
│   ├── syntaxes.git-hash
│   ├── update.sh
│   └── verify.sh
├── build.rs
├── config-file-schema.json
├── config.sample.yaml
├── docs/
│   ├── .gitignore
│   ├── book.toml
│   └── src/
│       ├── SUMMARY.md
│       ├── acknowledgements.md
│       ├── configuration/
│       │   ├── introduction.md
│       │   ├── options.md
│       │   └── settings.md
│       ├── features/
│       │   ├── code/
│       │   │   ├── d2.md
│       │   │   ├── execution.md
│       │   │   ├── highlighting.md
│       │   │   ├── latex.md
│       │   │   └── mermaid.md
│       │   ├── commands.md
│       │   ├── exports.md
│       │   ├── images.md
│       │   ├── introduction.md
│       │   ├── layout.md
│       │   ├── slide-transitions.md
│       │   ├── speaker-notes.md
│       │   └── themes/
│       │       ├── definition.md
│       │       └── introduction.md
│       ├── install.md
│       ├── internals/
│       │   └── parse.md
│       └── introduction.md
├── examples/
│   ├── README.md
│   ├── code.md
│   ├── columns.md
│   ├── custom-intro-slides.md
│   ├── demo.md
│   ├── footer.md
│   └── speaker-notes.md
├── executors.yaml
├── flake.nix
├── rustfmt.toml
├── scripts/
│   ├── generate-config-file-schema.sh
│   ├── parse-changelog.sh
│   ├── test-pdf-generation.sh
│   └── validate-config-file-schema.sh
├── src/
│   ├── code/
│   │   ├── execute.rs
│   │   ├── highlighting.rs
│   │   ├── mod.rs
│   │   ├── padding.rs
│   │   └── snippet.rs
│   ├── commands/
│   │   ├── keyboard.rs
│   │   ├── listener.rs
│   │   ├── mod.rs
│   │   └── speaker_notes.rs
│   ├── config.rs
│   ├── demo.rs
│   ├── export/
│   │   ├── exporter.rs
│   │   ├── html.rs
│   │   ├── mod.rs
│   │   ├── output.rs
│   │   └── script.js
│   ├── main.rs
│   ├── markdown/
│   │   ├── elements.rs
│   │   ├── html.rs
│   │   ├── mod.rs
│   │   ├── parse.rs
│   │   ├── text.rs
│   │   └── text_style.rs
│   ├── presentation/
│   │   ├── builder/
│   │   │   ├── comment.rs
│   │   │   ├── error.rs
│   │   │   ├── frontmatter.rs
│   │   │   ├── heading.rs
│   │   │   ├── images.rs
│   │   │   ├── list.rs
│   │   │   ├── mod.rs
│   │   │   ├── quote.rs
│   │   │   ├── snippet.rs
│   │   │   ├── sources.rs
│   │   │   ├── table.rs
│   │   │   └── tests.rs
│   │   ├── diff.rs
│   │   ├── mod.rs
│   │   └── poller.rs
│   ├── presenter.rs
│   ├── render/
│   │   ├── ascii_scaler.rs
│   │   ├── engine.rs
│   │   ├── layout.rs
│   │   ├── mod.rs
│   │   ├── operation.rs
│   │   ├── properties.rs
│   │   ├── text.rs
│   │   └── validate.rs
│   ├── resource.rs
│   ├── terminal/
│   │   ├── ansi.rs
│   │   ├── capabilities.rs
│   │   ├── emulator.rs
│   │   ├── image/
│   │   │   ├── mod.rs
│   │   │   ├── printer.rs
│   │   │   ├── protocols/
│   │   │   │   ├── ascii.rs
│   │   │   │   ├── iterm.rs
│   │   │   │   ├── kitty.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── raw.rs
│   │   │   │   └── sixel.rs
│   │   │   └── scale.rs
│   │   ├── mod.rs
│   │   ├── printer.rs
│   │   └── virt.rs
│   ├── theme/
│   │   ├── clean.rs
│   │   ├── mod.rs
│   │   ├── raw.rs
│   │   └── registry.rs
│   ├── third_party.rs
│   ├── tools.rs
│   ├── transitions/
│   │   ├── collapse_horizontal.rs
│   │   ├── fade.rs
│   │   ├── mod.rs
│   │   └── slide_horizontal.rs
│   ├── ui/
│   │   ├── execution/
│   │   │   ├── acquire_terminal.rs
│   │   │   ├── disabled.rs
│   │   │   ├── image.rs
│   │   │   ├── mod.rs
│   │   │   ├── output.rs
│   │   │   ├── pty.rs
│   │   │   └── validator.rs
│   │   ├── footer.rs
│   │   ├── mod.rs
│   │   ├── modals.rs
│   │   └── separator.rs
│   └── utils.rs
└── themes/
    ├── catppuccin-frappe.yaml
    ├── catppuccin-latte.yaml
    ├── catppuccin-macchiato.yaml
    ├── catppuccin-mocha.yaml
    ├── dark.yaml
    ├── gruvbox-dark.yaml
    ├── light.yaml
    ├── terminal-dark.yaml
    ├── terminal-light.yaml
    ├── tokyonight-day.yaml
    ├── tokyonight-moon.yaml
    ├── tokyonight-night.yaml
    └── tokyonight-storm.yaml

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
[*.sh]
indent_style = space
indent_size = 4


================================================
FILE: .github/FUNDING.yml
================================================
github: mfontanini


================================================
FILE: .github/workflows/docs.yaml
================================================
name: Deploy docs

on:
  push:
    branches:
      - master

permissions:
  contents: write

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install cargo-binstall
        uses: cargo-bins/cargo-binstall@v1.10.22

      - name: Install mdbook
        run: |
          cargo binstall -y mdbook@0.4.44 mdbook-alerts@0.7.0

      - name: Build the book
        run: |
          cd docs
          mdbook build

      - name: Deploy build to gh-pages branch
        uses: crazy-max/ghaction-github-pages@v4
        with:
          target_branch: gh-pages
          build_dir: docs/book 
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/merge.yaml
================================================
on:
  pull_request:
  push:
    branches:
      - master

name: Merge checks

jobs:
  check:
    name: Checks
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@1.90.0
        with:
          components: clippy

      - name: Run cargo check
        run: cargo check

      - name: Run cargo test
        run: cargo test

      - name: Run cargo clippy
        run: cargo clippy -- -D warnings

      - name: Install nightly toolchain
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: rustfmt

      - name: Run cargo fmt
        run: cargo +nightly fmt --all -- --check

      - name: Install uv
        uses: astral-sh/setup-uv@v5

      - name: Install weasyprint
        run: |
          uv venv
          source ./.venv/bin/activate
          uv pip install weasyprint

      - name: Export demo presentation as PDF and HTML
        run: |
          cat >/tmp/config.yaml <<EOL
          export:
            dimensions:
              rows: 35
              columns: 135
          EOL
          source ./.venv/bin/activate
          cargo run -- --export-pdf -c /tmp/config.yaml examples/demo.md
          cargo run -- --export-html -c /tmp/config.yaml examples/demo.md

  nix-flake:
    name: Validate nix flake
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install nix
        uses: DeterminateSystems/nix-installer-action@v17
      - name: Build
        run: nix build .#dev.presenterm

  bat-assets:
    name: Validate bat assets
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v2
      - name: Validate assets
        run: ./bat/verify.sh

  json-schemas:
    name: Validate JSON schemas
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v2
      - name: Validate config file schema
        run: |
          if ! ./scripts/validate-config-file-schema.sh; then
            echo -e "\033[31;1mRun ./scripts/generate-config-file-schema.sh to regenerate JSON schema"
            exit 1
          fi


================================================
FILE: .github/workflows/nightly.yaml
================================================
name: Nightly build

on:
  schedule:
    - cron: "0 0 * * *"

env:
  RELEASE_VERSION: nightly

jobs:
  vars:
    name: Set release variables
    runs-on: ubuntu-latest
    outputs:
      timestamp: ${{ steps.set.outputs.timestamp }}
      git_hash: ${{ steps.set.outputs.git_hash }}
      latest_nightly_hash: ${{ steps.set.outputs.latest_nightly_hash }}
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v4

      - name: Set variables
        id: set
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          set -euo pipefail
          timestamp=$(date -u)
          git_hash=$(git rev-parse HEAD)
          latest_nightly_hash=$(gh release view nightly | sed -n 's/.*based on ref \[\(.*\)\].*/\1/p')
          echo "timestamp=$timestamp" >> "$GITHUB_OUTPUT"
          echo "git_hash=$git_hash" >> "$GITHUB_OUTPUT"
          echo "latest_nightly_hash=$latest_nightly_hash" >> "$GITHUB_OUTPUT"

  publish-github:
    name: Publish on GitHub
    runs-on: ${{ matrix.config.OS }}
    needs: vars
    # Don't run this if the nightly hash already points to the current hash
    if: needs.vars.outputs.git_hash != needs.vars.outputs.latest_nightly_hash
    strategy:
      fail-fast: false
      matrix:
        config:
          - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-gnu" }
          - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-musl" }
          - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-gnu" }
          - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-musl" }
          - { OS: ubuntu-latest, TARGET: "armv5te-unknown-linux-gnueabi" }
          - { OS: ubuntu-latest, TARGET: "armv7-unknown-linux-gnueabihf" }
          - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-gnu" }
          - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-musl" }
          - { OS: macos-latest, TARGET: "x86_64-apple-darwin" }
          - { OS: macos-latest, TARGET: "aarch64-apple-darwin" }
          - { OS: windows-latest, TARGET: "x86_64-pc-windows-msvc" }
          - { OS: windows-latest, TARGET: "i686-pc-windows-msvc" }

    steps:
      - name: Checkout the repository
        uses: actions/checkout@v4

      - name: Build binary
        uses: houseabsolute/actions-rust-cross@a448c4b13769d56b63b035024fef8577e1d81915
        with:
          command: build
          toolchain: 1.90.0
          target: ${{ matrix.config.TARGET }}
          args: "--locked --release"

      - name: Prepare release assets
        shell: bash
        run: |
          mkdir release/
          cp {LICENSE,README.md} release/
          cp target/${{ matrix.config.TARGET }}/release/presenterm release/
          mv release/ presenterm-${{ env.RELEASE_VERSION }}/
      - name: Create release artifacts
        shell: bash
        run: |
          if [ "${{ matrix.config.OS }}" = "windows-latest" ]; then
            7z a -tzip "presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip" \
              presenterm-${{ env.RELEASE_VERSION }}
            sha512sum "presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip" \
              > presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip.sha512
          else
            tar -czvf presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \
              presenterm-${{ env.RELEASE_VERSION }}/
            shasum -a 512 presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \
              > presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz.sha512
          fi
      - name: Upload the release
        uses: svenstaro/upload-release-action@e2a63377780a8bacc68dcac9b0979ee20ad5a791
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          tag: nightly
          file: presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.*
          file_glob: true
          overwrite: true
          prerelease: true
          release_name: Nightly
          body: |
            This is a nightly build based on ref [${{ needs.vars.outputs.git_hash }}](https://github.com/mfontanini/presenterm/commit/${{ needs.vars.outputs.git_hash }})
            Generated on `${{ needs.vars.outputs.timestamp }}`


================================================
FILE: .github/workflows/release.yaml
================================================
name: Release

on:
  push:
    tags:
      - "v*.*.*"

jobs:
  changelog:
    name: Parse changelog
    runs-on: ubuntu-latest
    outputs:
      notes: ${{ steps.parse.outputs.notes }}
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v3

      - name: Parse release notes
        id: parse
        shell: bash
        run: |
          release_version=v${GITHUB_REF:11}
          r=$(./scripts/parse-changelog.sh "${release_version}")
          r="${r//'%'/'%25'}"
          r="${r//$'\n'/'%0A'}"
          r="${r//$'\r'/'%0D'}"
          echo "notes=$r" >> "$GITHUB_OUTPUT"

  publish-github:
    name: Publish on GitHub
    runs-on: ${{ matrix.config.OS }}
    needs: changelog
    strategy:
      fail-fast: false
      matrix:
        config:
          - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-gnu" }
          - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-musl" }
          - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-gnu" }
          - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-musl" }
          - { OS: ubuntu-latest, TARGET: "armv5te-unknown-linux-gnueabi" }
          - { OS: ubuntu-latest, TARGET: "armv7-unknown-linux-gnueabihf" }
          - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-gnu" }
          - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-musl" }
          - { OS: macos-latest, TARGET: "x86_64-apple-darwin" }
          - { OS: macos-latest, TARGET: "aarch64-apple-darwin" }
          - { OS: windows-latest, TARGET: "x86_64-pc-windows-msvc" }
          - { OS: windows-latest, TARGET: "i686-pc-windows-msvc" }

    steps:
      - name: Checkout the repository
        uses: actions/checkout@v4

      - name: Set the release version
        shell: bash
        run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV

      - name: Build binary
        uses: houseabsolute/actions-rust-cross@a448c4b13769d56b63b035024fef8577e1d81915
        with:
          command: build
          toolchain: 1.90.0
          target: ${{ matrix.config.TARGET }}
          args: "--locked --release"

      - name: Prepare release assets
        shell: bash
        run: |
          mkdir release/
          cp {LICENSE,README.md} release/
          cp target/${{ matrix.config.TARGET }}/release/presenterm release/
          mv release/ presenterm-${{ env.RELEASE_VERSION }}/

      - name: Create release artifacts
        shell: bash
        run: |
          if [ "${{ matrix.config.OS }}" = "windows-latest" ]; then
            7z a -tzip "presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip" \
              presenterm-${{ env.RELEASE_VERSION }}
            sha512sum "presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip" \
              > presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip.sha512
          else
            tar -czvf presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \
              presenterm-${{ env.RELEASE_VERSION }}/
            shasum -a 512 presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \
              > presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz.sha512
          fi

      - name: Upload the release
        uses: svenstaro/upload-release-action@e2a63377780a8bacc68dcac9b0979ee20ad5a791
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: presenterm-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.*
          file_glob: true
          overwrite: true
          release_name: v${{ env.RELEASE_VERSION }}
          tag: ${{ github.ref }}
          body: |
            ${{ needs.changelog.outputs.notes }}

  publish-crates-io:
    name: Publish on crates.io
    needs: publish-github
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v4

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@1.90.0

      - name: Publish
        run: cargo publish --locked --token ${{ secrets.CARGO_TOKEN }}


================================================
FILE: .gitignore
================================================
/target


================================================
FILE: CHANGELOG.md
================================================
# v0.16.1 - 2026-02-19

## New features

* Allow `italic` to be used as well as `italics` in theme ([#847](https://github.com/mfontanini/presenterm/issues/847)).

## Fixes

* Render modals at the center of the screen ([#848](https://github.com/mfontanini/presenterm/issues/848)).

## Docs

* Add styling docs to `slide_title` ([#845](https://github.com/mfontanini/presenterm/issues/845)) - thanks @0atman.
* Describe slide titles and headings better ([#846](https://github.com/mfontanini/presenterm/issues/846)).

# v0.16.0 - 2026-02-15

## Breaking changes

* Sixel is now supported in all platform and enabled by default. The will break any build scripts that enable the `sixel` feature flag since that is now gone. Any maintainer that is building the package and enabling that flag should no longer do so ([#828](https://github.com/mfontanini/presenterm/issues/828)).

## New features

* Allow [executing snippets inside a PTY](https://mfontanini.github.io/presenterm/features/code/execution.html#running-code-in-pseudo-terminal-pty). This allows you to run tools that move the cursor around and redraw the terminal inside a slide (e.g. `top`, `htop`, etc). ([#781](https://github.com/mfontanini/presenterm/issues/781)) ([#794](https://github.com/mfontanini/presenterm/issues/794)) ([#809](https://github.com/mfontanini/presenterm/issues/809)) ([#788](https://github.com/mfontanini/presenterm/issues/788)) ([#808](https://github.com/mfontanini/presenterm/issues/808)) ([#807](https://github.com/mfontanini/presenterm/issues/807)) ([#789](https://github.com/mfontanini/presenterm/issues/789)).
* Use `icy_sixel` crate instead of `sixel-rs`. `icy_sixel` is a pure rust crate which simplifies code distribution and allows enabling `sixel` support by default ([#818](https://github.com/mfontanini/presenterm/issues/818)) - thanks @gcavelier.
* Add support for [user comments](https://mfontanini.github.io/presenterm/features/commands.html#user-comments) in presentation rendering ([#773](https://github.com/mfontanini/presenterm/issues/773)).
* Allow passing in a [mermaid config file](https://mfontanini.github.io/presenterm/features/commands.html#mermaid) ([#833](https://github.com/mfontanini/presenterm/issues/833)).
* Allow specifying `mmdc` [puppeteer config path](https://mfontanini.github.io/presenterm/features/commands.html#mermaid) ([#830](https://github.com/mfontanini/presenterm/issues/830)) ([#842](https://github.com/mfontanini/presenterm/issues/842)).
* Add [keymap](https://mfontanini.github.io/presenterm/features/introduction.html#toggle-visual-grid) to toggle layout grid ([#718](https://github.com/mfontanini/presenterm/issues/718)).
* Add [`+auto_exec`](https://mfontanini.github.io/presenterm/features/code/execution.html#automatic-execution) attribute to snippets ([#732](https://github.com/mfontanini/presenterm/issues/732)).
* Update bat themes/syntaxes to latest to support a few new themes ([#811](https://github.com/mfontanini/presenterm/issues/811)).
* Add tokyonight moon/day/night themes ([#751](https://github.com/mfontanini/presenterm/issues/751)) - thanks @cloudlena.
* Allow configuring a global alignment in theme ([#801](https://github.com/mfontanini/presenterm/issues/801)).
* Add dynamic theme option (light/dark) based on terminal color ([#778](https://github.com/mfontanini/presenterm/issues/778)) - thanks @JOTSR.
* Add common es executors and support jsx and ts(x) snippets ([#783](https://github.com/mfontanini/presenterm/issues/783)) - thanks @JOTSR.
* Allow configuring code block line numbers at theme level ([#771](https://github.com/mfontanini/presenterm/issues/771)).
* Allow setting prefix on slide titles ([#739](https://github.com/mfontanini/presenterm/issues/739)).
* Allow configuring whether first h1 heading is slide title ([#738](https://github.com/mfontanini/presenterm/issues/738)) ([#756](https://github.com/mfontanini/presenterm/issues/756)).
* Allow styling bold/italics ([#737](https://github.com/mfontanini/presenterm/issues/737)).
* Respect `pause` in speaker notes ([#735](https://github.com/mfontanini/presenterm/issues/735)).
* Add `--list-comment-commands` cli option ([#723](https://github.com/mfontanini/presenterm/issues/723)) - thanks @rochacbruno.
* Allow setting headings to be bold/italics/underlined ([#721](https://github.com/mfontanini/presenterm/issues/721)).
* Add `typescript-react/tsx` highlighting ([#777](https://github.com/mfontanini/presenterm/issues/777)) - thanks @JOTSR.
* Add dart code highlighting #779 ([#780](https://github.com/mfontanini/presenterm/issues/780)) - thanks @alycda.
* Add ms windows executors and highlight (`cmd`, `wsl`, `bat`, `pwsh`) ([#799](https://github.com/mfontanini/presenterm/issues/799)) - thanks @JOTSR.
* Add Elixir to executors ([#709](https://github.com/mfontanini/presenterm/issues/709)) - thanks @kevinschweikert.
* Support gdscript syntax highlighting ([#820](https://github.com/mfontanini/presenterm/issues/820)) - thanks @TitanNano.

## Fixes

* Use right size for footer images ([#840](https://github.com/mfontanini/presenterm/issues/840)).
* Don't crash when exporting `+image` snippets ([#827](https://github.com/mfontanini/presenterm/issues/827)).
* Clippy useless conversion ([#805](https://github.com/mfontanini/presenterm/issues/805)) - thanks @JOTSR.
* Preserve footnote definition location ([#803](https://github.com/mfontanini/presenterm/issues/803)).
* Respect global alignment for lists ([#802](https://github.com/mfontanini/presenterm/issues/802)).
* Don't crash sending event if presentation is in error state ([#800](https://github.com/mfontanini/presenterm/issues/800)).
* Highlight php code even if it doesn't start with "<?php" ([#796](https://github.com/mfontanini/presenterm/issues/796)).
* Handle dark/light colors properly when converting from 8bt ([#793](https://github.com/mfontanini/presenterm/issues/793)).
* Use legible color in tokyonight-day's block quote/alert style ([#792](https://github.com/mfontanini/presenterm/issues/792)).
* Allow column layouts in included files ([#776](https://github.com/mfontanini/presenterm/issues/776)).
* Use `show_pauses` in sample config ([#745](https://github.com/mfontanini/presenterm/issues/745)).
* Don't consider prefix part of the title ([#740](https://github.com/mfontanini/presenterm/issues/740)).
* Keep state between pauses on pause-new-slide ([#731](https://github.com/mfontanini/presenterm/issues/731)).
* Don't add extra heading lines depending on font size ([#719](https://github.com/mfontanini/presenterm/issues/719)).
* Consider color range 0x08.. - 0x0f.. in bat themes ([#706](https://github.com/mfontanini/presenterm/issues/706)).

## Chore

* Increase async render polling speed ([#806](https://github.com/mfontanini/presenterm/issues/806)).
* Add script to generate config file json schema ([#791](https://github.com/mfontanini/presenterm/issues/791)).
* Restructure snippet execution attributes ([#787](https://github.com/mfontanini/presenterm/issues/787)).
* Bump dependencies ([#772](https://github.com/mfontanini/presenterm/issues/772)).
* Unify text styling based on theme ([#734](https://github.com/mfontanini/presenterm/issues/734)).

## Docs

* Fix typo in config theme section ([#804](https://github.com/mfontanini/presenterm/issues/804)) - thanks @JOTSR.
* Fix typo in code execution docs ([#782](https://github.com/mfontanini/presenterm/issues/782)) - thanks @gcavelier.
* Sync supported terminals ([#722](https://github.com/mfontanini/presenterm/issues/722)) - thanks @gcavelier.
* Document overflow validation ([#712](https://github.com/mfontanini/presenterm/issues/712)).
* Add new sample presentation about ratatui on embedded ([#817](https://github.com/mfontanini/presenterm/issues/817)) - thanks @Vaishnav-Sabari-Girish.
* Add new sample presentation about Hayasen library ([#813](https://github.com/mfontanini/presenterm/issues/813)) - thanks @Vaishnav-Sabari-Girish.

## ❤️ Sponsors

Thanks to the following users who supported _presenterm_ via a [github sponsorship](https://github.com/sponsors/mfontanini) in this release:

* [@0atman](https://github.com/0atman)
* [@orhun](https://github.com/orhun)
* [@gwpl](https://github.com/gwpl)
* [@ADS-Fund](https://github.com/ADS-Fund)
* [@jonas-grobe](https://github.com/jonas-grobe)
* [@sidju](https://github.com/sidju)
* [@alycda](https://github.com/alycda)

# v0.15.1 - 2025-08-01

## Fixes

* Disable OSC 11 when running in tmux ([#696](https://github.com/mfontanini/presenterm/issues/696)).
* Follow custom theme symlinks ([#692](https://github.com/mfontanini/presenterm/issues/692)).

# v0.15.0 - 2025-07-13

## Breaking changes

* The behavior for "jump next fast" and "jump previous fast" keybindings (defaults to `n` and `p`) now jumps straight from one slide to the next/previous one ignoring pauses. Before this used to "reveal" all pauses when jumping forward before going to the next slide. This behavior was weird and unintuitive so now fast jumps go straight into the next/previous slides. The action of "showing all pauses on the current slide" can now be done by pressing `s` ([#678](https://github.com/mfontanini/presenterm/issues/678)).

## New features

* Allow specifying where a [snippet's execution output will go](https://mfontanini.github.io/presenterm/features/code/execution.html#output-placing) ([#658](https://github.com/mfontanini/presenterm/issues/658)).
* Add `include` comment command to [import markdown files](https://mfontanini.github.io/presenterm/features/commands.html#including-external-markdown-files) ([#651](https://github.com/mfontanini/presenterm/issues/651)) ([#683](https://github.com/mfontanini/presenterm/issues/683)).
* Allow [validating snippets without explicitly executing them](https://mfontanini.github.io/presenterm/features/code/execution.html#validating-snippets) by using `--validate-snippets` switch ([#645](https://github.com/mfontanini/presenterm/issues/645)) ([#637](https://github.com/mfontanini/presenterm/issues/637)).
* Support iterm2 image protocol when running in tmux ([#661](https://github.com/mfontanini/presenterm/issues/661)).
* Add support for [d2 diagrams](https://mfontanini.github.io/presenterm/features/code/d2.html) ([#657](https://github.com/mfontanini/presenterm/issues/657)).
* Errors encountered when parsing markdown now always display the file, line, and column where the error was found, as well as the markdown line that caused the error ([#674](https://github.com/mfontanini/presenterm/issues/674)) ([#653](https://github.com/mfontanini/presenterm/issues/653)) ([#684](https://github.com/mfontanini/presenterm/issues/684)) ([#685](https://github.com/mfontanini/presenterm/issues/685)).
* Superscript via `^this^` and `<sup>this</sup>` syntaxes is supported when using the kitty terminal. For other terminals we try to use unicode half block characters which cover a portion of the ASCII charset. ([#606](https://github.com/mfontanini/presenterm/issues/606))([#617](https://github.com/mfontanini/presenterm/issues/617) ) ([#665](https://github.com/mfontanini/presenterm/issues/665)).
* Allow [alternative snippet executors](https://mfontanini.github.io/presenterm/features/code/execution.html#alternative-executors) for languages that support execution. This allows, for example, runnig rust code via `rust-script` or python code via `pytest` ([#614](https://github.com/mfontanini/presenterm/issues/614)).
* Allow using env var `PRESENTERM_CONFIG_FILE` to point to the config file ([#663](https://github.com/mfontanini/presenterm/issues/663)) - thanks @Silver-Golden.
* Set background color via OSC 11 to avoid having a colored edge around the presentation ([#623](https://github.com/mfontanini/presenterm/issues/623)) ([#624](https://github.com/mfontanini/presenterm/issues/624)) ([#627](https://github.com/mfontanini/presenterm/issues/627)).
* Add support for markdown footnotes ([#616](https://github.com/mfontanini/presenterm/issues/616)).
* Runtime errors are now centered rather than being left aligned with some fixed margin ([#638](https://github.com/mfontanini/presenterm/issues/638)).
* Allow [configuring number of newlines](https://mfontanini.github.io/presenterm/features/commands.html#number-of-lines-in-between-list-items) in between list items ([#628](https://github.com/mfontanini/presenterm/issues/628)).
* Allow 3 digit hex colors ([#609](https://github.com/mfontanini/presenterm/issues/609)) - thanks @peterc-s.
* Allow [configuring font](https://mfontanini.github.io/presenterm/configuration/settings.html#pdf-font) used in PDF export ([#608](https://github.com/mfontanini/presenterm/issues/608)).
* Added `uv` as an alternative executor for python code ([#662](https://github.com/mfontanini/presenterm/issues/662)) - thanks @JanNeuendorf.
* Allow multiline slide titles ([#679](https://github.com/mfontanini/presenterm/issues/679)).
* Add support for multiline slide titles ([#682](https://github.com/mfontanini/presenterm/issues/682)) - thanks @barr-israel.
* Add support for multiline subtitle ([#680](https://github.com/mfontanini/presenterm/issues/680)) - thanks @barr-israel.
* Add support for syntax highlighting and execution for F# ([#650](https://github.com/mfontanini/presenterm/issues/650)) - thanks @mnebes.
* Use text style/colors in rust-script errors ([#644](https://github.com/mfontanini/presenterm/issues/644)).
* Added `rust-script-pedantic` alternative executor for rust ([#640](https://github.com/mfontanini/presenterm/issues/640)).

## Fixes

* Consider rect start row when capping max terminal rows ([#656](https://github.com/mfontanini/presenterm/issues/656)).
* Skip speaker notes slide on `skip_slide` ([#625](https://github.com/mfontanini/presenterm/issues/625)).
* Don't loop on 0 bytes read when querying capabilities ([#620](https://github.com/mfontanini/presenterm/issues/620)).
* Make code snippet language specifiers case insensitive ([#613](https://github.com/mfontanini/presenterm/issues/613)) - thanks @peterc-s.
* Bump dependencies ([#681](https://github.com/mfontanini/presenterm/issues/681)) - thanks @barr-israel.

## Chore

* Refactored code to make it more easily testeable, and added lots of tests to ensure markdown is rendered as expected. This will hopefully reduce the number of errors found after each release ([#660](https://github.com/mfontanini/presenterm/issues/660)) ([#659](https://github.com/mfontanini/presenterm/issues/659)) ([#655](https://github.com/mfontanini/presenterm/issues/655)) ([#647](https://github.com/mfontanini/presenterm/issues/647)).
* Bump rust version to 1.82 ([#611](https://github.com/mfontanini/presenterm/issues/611)).
* Perform better validation around matching HTML tags ([#668](https://github.com/mfontanini/presenterm/issues/668)).
* Don't run nightly job if the git hash hasn't changed ([#667](https://github.com/mfontanini/presenterm/issues/667)) ([#675](https://github.com/mfontanini/presenterm/issues/675)) ([#669](https://github.com/mfontanini/presenterm/issues/669)).
* Display an error when using http(s) urls in image tags ([#666](https://github.com/mfontanini/presenterm/issues/666)).
* Update Catppuccin themes to use palettes ([#672](https://github.com/mfontanini/presenterm/issues/672)) - thanks @jmcharter.

## Docs

* Add custom introduction slides example ([#633](https://github.com/mfontanini/presenterm/issues/633)).
* Add mention of `winget` ([#621](https://github.com/mfontanini/presenterm/issues/621)) - thanks @DeveloperPaul123.
* Fix incorrect note callout ([#610](https://github.com/mfontanini/presenterm/issues/610)) - thanks @Sacquer.
* Add a note to export pdf using `uv` ([#646](https://github.com/mfontanini/presenterm/issues/646)) - thanks @PitiBouchon.
* Clarify why no remote urls work with images ([#664](https://github.com/mfontanini/presenterm/issues/664)) - thanks @ryuheechul.

## ❤️ Sponsors

Thanks to the following users who supported _presenterm_ via a [github sponsorship](https://github.com/sponsors/mfontanini) in this release:

* [@0atman](https://github.com/0atman)
* [@orhun](https://github.com/orhun)
* [@gwpl](https://github.com/gwpl)

# v0.14.0 - 2025-05-17

## New features

* Add support for [exporting presentations as HTML files](https://mfontanini.github.io/presenterm/features/exports.html#html) ([#566](https://github.com/mfontanini/presenterm/issues/566)) ([#595](https://github.com/mfontanini/presenterm/issues/595)) ([#575](https://github.com/mfontanini/presenterm/issues/575)) ([#599](https://github.com/mfontanini/presenterm/issues/599)) - thanks @JustSimplyKyle.
* Snippet execution output now contains configurable padding and built-in themes default to the same padding as snippets (2 spaces horizontally, one line vertically) ([#592](https://github.com/mfontanini/presenterm/issues/592)) ([#593](https://github.com/mfontanini/presenterm/issues/593)).
* Add highlighting and execution support for Jsonnet ([#585](https://github.com/mfontanini/presenterm/issues/585)) - thanks @imobachgs.
* Allow [configuring snippets](https://mfontanini.github.io/presenterm/configuration/settings.html#sequential-snippet-execution) to be executed sequentially during exports ([#584](https://github.com/mfontanini/presenterm/issues/584)).

## Fixes

* Skip slides with pauses correctly ([#598](https://github.com/mfontanini/presenterm/issues/598)).
* Avoid printing text if there's no vertical space for it, which otherwise looks bad particularly when using font size > 1 ([#594](https://github.com/mfontanini/presenterm/issues/594)).
* Execute snippets only once during export ([#583](https://github.com/mfontanini/presenterm/issues/583)).
* Don't add an extra pause after lists if there's nothing left ([#580](https://github.com/mfontanini/presenterm/issues/580)).
* Allow interleaved spans and variables in footer ([#577](https://github.com/mfontanini/presenterm/issues/577)).
* Truly center `+exec_replace` snippet output ([#572](https://github.com/mfontanini/presenterm/issues/572)).

## Docs

* Added link to public presentation using presenterm ([#589](https://github.com/mfontanini/presenterm/issues/589)) - thanks @pwnwriter.
* Rename parameter name to the correct one in docs ([#570](https://github.com/mfontanini/presenterm/issues/570)) - thanks @DzuWe.
* Fix typo in highlighting.md ([#586](https://github.com/mfontanini/presenterm/issues/586)) - thanks @0atman.

## Chore

* Bump dependencies ([#596](https://github.com/mfontanini/presenterm/issues/596)).

## ❤️ Sponsors

Thanks to the following users who supported _presenterm_ via a [github sponsorship](https://github.com/sponsors/mfontanini) in this release:

* [@0atman](https://github.com/0atman)
* [@orhun](https://github.com/orhun)

# v0.13.0 - 2025-04-25

## Breaking changes

* The CLI parameter to generate the JSON schema for the config file (`--generate-config-file-schema`) is now hidden behind a `json-schema` feature flag. The JSON schema file for the latest version is already publicly available  at `https://github.com/mfontanini/presenterm/blob/${VERSION}/config-file-schema.json`, so anyone can use it without having to generate it by hand. This allows cutting down the number of dependencies in this project quite a bit ([#563](https://github.com/mfontanini/presenterm/issues/563)).

## New features

* Support for [slide transitions](https://mfontanini.github.io/presenterm/features/slide-transitions.html) is now available ([#530](https://github.com/mfontanini/presenterm/issues/530)):
  * Add fade slide transition ([#534](https://github.com/mfontanini/presenterm/issues/534)).
  * Add slide horizontally slide transition animation ([#528](https://github.com/mfontanini/presenterm/issues/528)).
  * Add `collapse_horizontal` slide transition ([#560](https://github.com/mfontanini/presenterm/issues/560)).
* Add `--output` option to specify the path where the output file is written to during an export ([#526](https://github.com/mfontanini/presenterm/issues/526)) - thanks @marianozunino.
* Allow specifying [start/end lines](https://mfontanini.github.io/presenterm/features/code/highlighting.html#including-external-code-snippets) in file snippet type ([#565](https://github.com/mfontanini/presenterm/issues/565)).
* Allow letting [pauses become new slides](https://mfontanini.github.io/presenterm/configuration/settings.html#pause-behavior) when exporting ([#557](https://github.com/mfontanini/presenterm/issues/557)).
* Allow [using images on right in footer](https://mfontanini.github.io/presenterm/features/themes/definition.html#footer-images) ([#554](https://github.com/mfontanini/presenterm/issues/554)).
* Add [`max_rows` configuration](https://mfontanini.github.io/presenterm/configuration/settings.html#maximum-presentation-height) to cap vertical size ([#531](https://github.com/mfontanini/presenterm/issues/531)).
* Add julia language highlighting and execution support ([#561](https://github.com/mfontanini/presenterm/issues/561)).

## Fixes

* Center overflow lines when using centered text ([#546](https://github.com/mfontanini/presenterm/issues/546)).
* Don't add extra space before heading if prefix in theme is empty ([#542](https://github.com/mfontanini/presenterm/issues/542)).
* Use no typst background in terminal-* built in themes ([#535](https://github.com/mfontanini/presenterm/issues/535)).
* Use `std::env::temp_dir` in the `external_snippet` test ([#533](https://github.com/mfontanini/presenterm/issues/533)) - thanks @Medovi.
* Respect `extends` in a theme set via `path` in front matter ([#532](https://github.com/mfontanini/presenterm/issues/532)).

## Misc

* Refactor async renders (e.g. mermaid/typst/latex `+render` blocks, `+exec` blocks, etc) to work truly asynchronously. This causes the output to be polled faster, and causes jumping to a slide that contains an async render to take a likely negligible (but maybe noticeable) amount of time to be jumped to. This was needed for slide transitions to work seemlessly ([#556](https://github.com/mfontanini/presenterm/issues/556)).
* Get rid of `textproperties` ([#529](https://github.com/mfontanini/presenterm/issues/529)).
* Add links to presentations using presenterm ([#544](https://github.com/mfontanini/presenterm/issues/544)) - thanks @orhun.

## Performance improvements

* A few performance improvements had to be done for slide transitions to work seemlessly:
  * Pre-scale ASCII images when transitions are enabled ([#550](https://github.com/mfontanini/presenterm/issues/550)).
  * Pre-scale generated images ([#553](https://github.com/mfontanini/presenterm/issues/553)).
  * Cache resized ASCII images ([#547](https://github.com/mfontanini/presenterm/issues/547)).

## ❤️ Sponsors

Thanks to the following users who supported _presenterm_ via a [github sponsorship](https://github.com/sponsors/mfontanini) in this release:

* [@0atman](https://github.com/0atman)
* [@orhun](https://github.com/orhun)
* [@fipoac](https://github.com/fipoac)

# v0.12.0 - 2025-03-24

## Breaking changes

* Using incremental lists now adds an extra pause before and after a list. Use the `defaults.incremental_lists` [configuration parameter](https://mfontanini.github.io/presenterm/features/commands.html#incremental-lists-behavior) to go back to the previous behavior ([#487](https://github.com/mfontanini/presenterm/issues/487)) ([#498](https://github.com/mfontanini/presenterm/issues/498)).

## New features

* [PDF exports](https://mfontanini.github.io/presenterm/features/pdf-export.html) are now generated by invoking [weasyprint](https://pypi.org/project/weasyprint/) rather than by using the now deprecated _presenterm-export_. This gets rid of the need for _tmux_ and opens up the door for other export formats ([#509](https://github.com/mfontanini/presenterm/issues/509)) ([#517](https://github.com/mfontanini/presenterm/issues/517)).
* PDF export dimensions can now also be [specified in the config file](https://mfontanini.github.io/presenterm/configuration/settings.html#pdf-export-size) rather than always having them inferred by the terminal size ([#511](https://github.com/mfontanini/presenterm/issues/511)).
* Allow specifying path for temporary files generated during presentation export ([#518](https://github.com/mfontanini/presenterm/issues/518)).
* Respect font sizes in generated PDF ([#510](https://github.com/mfontanini/presenterm/issues/510)).
* Add [`skip_slide` comment command](https://mfontanini.github.io/presenterm/features/commands.html#skip-slide) to avoid including a slide in the final presentation ([#505](https://github.com/mfontanini/presenterm/issues/505)).
* Add [`alignment` comment](https://mfontanini.github.io/presenterm/features/commands.html#text-alignment) command to specify text alignment for the remainder of a slide ([#493](https://github.com/mfontanini/presenterm/issues/493)) ([#522](https://github.com/mfontanini/presenterm/issues/522)).
* Add `--current-theme` CLI parameter to display the theme being used ([#489](https://github.com/mfontanini/presenterm/issues/489)).
* Add gruvbox dark theme ([#483](https://github.com/mfontanini/presenterm/issues/483)) - thanks @ret2src.

## Fixes

* Fix broken ANSI escape code parsing which would cause command output to sometimes be incorrectly parsed and therefore led to its colors/attributes not being respected ([#500](https://github.com/mfontanini/presenterm/issues/500)).
* Center lists correctly ([#512](https://github.com/mfontanini/presenterm/issues/512)) ([#520](https://github.com/mfontanini/presenterm/issues/520)).
* Respect end slide shorthand in speaker notes mode ([#494](https://github.com/mfontanini/presenterm/issues/494)).
* Use more visible colors in snippet execution output in terminal-light/dark themes ([#485](https://github.com/mfontanini/presenterm/issues/485)).
* Show error if sixel mode is selected but disabled ([#525](https://github.com/mfontanini/presenterm/issues/525)).

## CI

* Add nightly build job ([#496](https://github.com/mfontanini/presenterm/issues/496)).

## Docs

* Fix typo in README.md ([#490](https://github.com/mfontanini/presenterm/issues/490)) - thanks @eltociear.
* Correctly include layout pic ([#495](https://github.com/mfontanini/presenterm/issues/495)) - thanks @Tuxified.

## Misc

* Cleanup text attributes ([#519](https://github.com/mfontanini/presenterm/issues/519)).
* Refactor snippet processing ([#484](https://github.com/mfontanini/presenterm/issues/484)).

## Sponsors

It is now possible to sponsor this project via [github sponsors](https://github.com/sponsors/mfontanini).

Thanks to [@0atman](https://github.com/0atman) for being the first project sponsor!

# v0.11.0 - 2025-03-08

## Breaking changes

* Footer templates are now sanitized, and any variables surrounded in braces that aren't supported (e.g. `{potato}`) will now cause _presenterm_ to display an error. If you'd like to use braces in contexts where you're not trying to reference a variable you can use double braces, e.g. `live at {{PotatoConf}}` ([#442](https://github.com/mfontanini/presenterm/issues/442)) ([#467](https://github.com/mfontanini/presenterm/issues/467)) ([#469](https://github.com/mfontanini/presenterm/issues/469)) ([#471](https://github.com/mfontanini/presenterm/issues/471)).

## New features

* [Add support for kitty's font size protocol](https://mfontanini.github.io/presenterm/features/introduction.html#font-sizes). This is now used by default in built in themes in a few components such as the intro slide's title and slide titles. See the [example presentation gif](https://github.com/mfontanini/presenterm/blob/master/docs/src/assets/demo.gif) to check out how this looks like. Terminal suport for this feature is detected on startup and will be ignored if unsupported. This requires _kitty_ >= 0.40.0 ([#438](https://github.com/mfontanini/presenterm/issues/438)) ([#460](https://github.com/mfontanini/presenterm/issues/460)) ([#470](https://github.com/mfontanini/presenterm/issues/470)).
* [Allow specifying font size in a comment command](https://mfontanini.github.io/presenterm/features/commands.html#font-size), which causes any subsequent text in a slide to use the specified font size. Just like the above, only supported in _kitty_ >= 0.40.0 for now ([#458](https://github.com/mfontanini/presenterm/issues/458)).
* [Footers can now contain images](https://mfontanini.github.io/presenterm/features/themes/definition.html#footer-images) in the left and center components. This allows including some form of branding/company logo to your presentations ([#450](https://github.com/mfontanini/presenterm/issues/450)) ([#476](https://github.com/mfontanini/presenterm/issues/476)).
* [Footers can now contain inline markdown](https://mfontanini.github.io/presenterm/features/themes/definition.html#template-footers), which allows using bold, italics, `<span>` tags for colors, etc ([#466](https://github.com/mfontanini/presenterm/issues/466)).
* [Presentation titles can now contain inline markdown](https://mfontanini.github.io/presenterm/features/introduction.html#introduction-slide) ([#464](https://github.com/mfontanini/presenterm/issues/464)).
* [Introduce palette.classes in themes](https://mfontanini.github.io/presenterm/features/themes/definition.html#color-palette) to allow specifying combinations of foreground/background colors that can be referenced via the `class` attribute in `<span>` tags ([#468](https://github.com/mfontanini/presenterm/issues/468)).
* It's now possible to [configure the alignment](https://mfontanini.github.io/presenterm/configuration/settings.html#maximum-presentation-width) to use when `max_columns` is configured and the terminal width is larger than it ([#475](https://github.com/mfontanini/presenterm/issues/475)).
* Add support for wikilinks ([#448](https://github.com/mfontanini/presenterm/issues/448)).

## Fixes

* Don't get stuck if tmux doesn't passthrough ([#456](https://github.com/mfontanini/presenterm/issues/456)).
* Don't squash image if terminal's font aspect ratio is not 2:1 ([#446](https://github.com/mfontanini/presenterm/issues/446)).
* Fail if `--config-file` points to non existent file ([#474](https://github.com/mfontanini/presenterm/issues/474)).
* Use right script name for kotlin files when executing ([#462](https://github.com/mfontanini/presenterm/issues/462)).
* Respect lists that start at non 1 indexes ([#459](https://github.com/mfontanini/presenterm/issues/459)).
* Jump to right slide on code attribute change ([#478](https://github.com/mfontanini/presenterm/issues/478)).

## Improvements

* Remove `result` return type from builder fns that don't need it ([#465](https://github.com/mfontanini/presenterm/issues/465)).
* Refactor theme code ([#463](https://github.com/mfontanini/presenterm/issues/463)).
* Restructure `terminal` code and add test for margins/layouts ([#443](https://github.com/mfontanini/presenterm/issues/443)).
* Use `fastrand` instead of `rand` ([#441](https://github.com/mfontanini/presenterm/issues/441)).
* Avoid cloning strings when styling them ([#440](https://github.com/mfontanini/presenterm/issues/440)).

# v0.10.1 - 2025-02-14

## Fixes

* Don't error out if `options` in front matter doesn't include `auto_render_languages` ([#454](https://github.com/mfontanini/presenterm/pull/454)).
* Bump sixel-rs to 0.4.1 to fix build in aarch64 and riscv64 ([#452](https://github.com/mfontanini/presenterm/pull/452)) - thanks @Xeonacid.

# v0.10.0 - 2025-02-02

## New features

* Support for presentation speaker notes ([#389](https://github.com/mfontanini/presenterm/issues/389)) ([#419](https://github.com/mfontanini/presenterm/issues/419)) ([#421](https://github.com/mfontanini/presenterm/issues/421)) ([#425](https://github.com/mfontanini/presenterm/issues/425)) - thanks @dmackdev.
* Add support for colored text via inline `span` HTML tags  ([#390](https://github.com/mfontanini/presenterm/issues/390)).
* Add a color palette in themes to allow reusing colors across the theme and using predefined colors inside `span` tags ([#427](https://github.com/mfontanini/presenterm/issues/427)).
* Add support for github/gitlab style markdown alerts ([#423](https://github.com/mfontanini/presenterm/issues/423)) ([#430](https://github.com/mfontanini/presenterm/issues/430)).
* Allow using `+image` on code blocks to consume their output as an image ([#429](https://github.com/mfontanini/presenterm/issues/429)).
* Allow multiline comment commands ([#424](https://github.com/mfontanini/presenterm/issues/424)).
* Allow auto rendering mermaid/typst/latex code blocks ([#418](https://github.com/mfontanini/presenterm/issues/418)).
* Allow capping max columns on presentation ([#417](https://github.com/mfontanini/presenterm/issues/417)).
* Automatically detect kitty support, including when running inside tmux ([#406](https://github.com/mfontanini/presenterm/issues/406)).
* Use kitty image protocol in ghostty ([#405](https://github.com/mfontanini/presenterm/issues/405)).
* Force color output in rust, c, and c++ compiler executions ([#401](https://github.com/mfontanini/presenterm/issues/401)).
* Add graphql code highlighting ([#385](https://github.com/mfontanini/presenterm/issues/385)) - thanks @GV14982.
* Add tcl code highlighting ([#387](https://github.com/mfontanini/presenterm/issues/387)) - thanks @jtplaarj.
* Add Haskell executor ([#414](https://github.com/mfontanini/presenterm/issues/414)) - thanks @feature-not-a-bug.
* Add C# to code executors ([#399](https://github.com/mfontanini/presenterm/issues/399)) - thanks @giggio.
* Add R to executors ([#393](https://github.com/mfontanini/presenterm/issues/393)) - thanks @jonocarroll.

## Fixes

* Check for `term_program` before `term` to determine emulator ([#420](https://github.com/mfontanini/presenterm/issues/420)).
* Allow jumping back to column in column layout ([#396](https://github.com/mfontanini/presenterm/issues/396)).
* Ignore comments that start with `vim:` prefix ([#395](https://github.com/mfontanini/presenterm/issues/395)).
* Respect `+no_background` on a `+exec_replace` block ([#383](https://github.com/mfontanini/presenterm/issues/383)).

## Docs

* Document tmux active session bug ([#402](https://github.com/mfontanini/presenterm/issues/402)).
* Add notes on running `bat` directly ([#397](https://github.com/mfontanini/presenterm/issues/397)).

# v0.9.0 - 2024-10-06

## Breaking changes

* Default themes now no longer use a progress bar based footer. Instead they use indicator of the current page number 
and the total number of pages. If you'd like to preserve the old behavior, you can override the theme by using 
`footer.style = progress_bar` in [your 
theme](https://mfontanini.github.io/presenterm/guides/themes.html#setting-themes).
* Links that include a title (e.g. `[my title](http://example.com)`) now have their title rendered as well. Removing a 
link's title will make it look the same as they used to.

## New features

* Use "template" footer in built-in themes ([#358](https://github.com/mfontanini/presenterm/issues/358)).
* Allow including external code snippets ([#328](https://github.com/mfontanini/presenterm/issues/328)) 
  ([#372](https://github.com/mfontanini/presenterm/issues/372)).
* Add `+no_background` property to remove background from code blocks 
  ([#363](https://github.com/mfontanini/presenterm/issues/363)) 
  ([#368](https://github.com/mfontanini/presenterm/issues/368)).
* Show colored output from snippet execution output ([#316](https://github.com/mfontanini/presenterm/issues/316)).
* Style markdown inside block quotes ([#350](https://github.com/mfontanini/presenterm/issues/350)) 
  ([#351](https://github.com/mfontanini/presenterm/issues/351)).
* Allow using all intro slide variables in footer template 
  ([#338](https://github.com/mfontanini/presenterm/issues/338)).
* Include hidden line prefix in executors file ([#337](https://github.com/mfontanini/presenterm/issues/337)).
* Show link labels and titles ([#334](https://github.com/mfontanini/presenterm/issues/334)).
* Add `+exec_replace` which executes snippets and replaces them with their output 
  ([#330](https://github.com/mfontanini/presenterm/issues/330)) 
  ([#371](https://github.com/mfontanini/presenterm/issues/371)).
* Always show snippet execution bar ([#329](https://github.com/mfontanini/presenterm/issues/329)).
* Handle suspend signal (SIGTSTP) ([#318](https://github.com/mfontanini/presenterm/issues/318)).
* Allow closing with `q` ([#321](https://github.com/mfontanini/presenterm/issues/321)).
* Add event, location, and date labels in intro slide ([#317](https://github.com/mfontanini/presenterm/issues/317)).
* Use transparent background in mermaid charts ([#314](https://github.com/mfontanini/presenterm/issues/314)).
* Add `+acquire_terminal` to acquire the terminal when running snippets 
  ([#366](https://github.com/mfontanini/presenterm/issues/366))
  ([#376](https://github.com/mfontanini/presenterm/pull/376)).
* Add PHP executor ([#332](https://github.com/mfontanini/presenterm/issues/332)).
* Add Racket syntax highlighting ([#367](https://github.com/mfontanini/presenterm/issues/367)).
* Add TOML highlighting ([#361](https://github.com/mfontanini/presenterm/issues/361)).

## Fixes

* Wrap code snippets if they don't fit in terminal ([#320](https://github.com/mfontanini/presenterm/issues/320)).
* Allow list-themes/acknowledgements to run without path ([#359](https://github.com/mfontanini/presenterm/issues/359)).
* Translate tabs in code snippets to 4 spaces ([#356](https://github.com/mfontanini/presenterm/issues/356)).
* Add padding to right of code block wrapped lines ([#354](https://github.com/mfontanini/presenterm/issues/354)).
* Don't wrap code snippet separator line ([#353](https://github.com/mfontanini/presenterm/issues/353)).
* Show block quote prefix when wrapping ([#352](https://github.com/mfontanini/presenterm/issues/352)).
* Don't crash on code block with only hidden-line-prefixed lines 
  ([#347](https://github.com/mfontanini/presenterm/issues/347)).
* Canonicalize resources path ([#333](https://github.com/mfontanini/presenterm/issues/333)).
* Execute script relative to current working directory ([#323](https://github.com/mfontanini/presenterm/issues/323)).
* Support rendering mermaid charts on windows ([#319](https://github.com/mfontanini/presenterm/issues/319)).

## Improvements

* Add example on how column layouts and pauses interact ([#348](https://github.com/mfontanini/presenterm/issues/348)).
* Rename `jump_to_vertical_center` -> `jump_to_middle` in docs 
  ([#342](https://github.com/mfontanini/presenterm/issues/342)).
* Document `all` snippet highlighting keyword ([#335](https://github.com/mfontanini/presenterm/issues/335)).

# v0.8.0 - 2024-07-29

## Breaking changes

* Force users to explicitly enable snippet execution ([#276](https://github.com/mfontanini/presenterm/issues/276)) ([#281](https://github.com/mfontanini/presenterm/issues/281)).

## New features

* Code snippet execution for various programming languages ([#253](https://github.com/mfontanini/presenterm/issues/253)) ([#255](https://github.com/mfontanini/presenterm/issues/255)) ([#256](https://github.com/mfontanini/presenterm/issues/256)) ([#258](https://github.com/mfontanini/presenterm/issues/258)) ([#282](https://github.com/mfontanini/presenterm/issues/282)).
* Allow executing compiled snippets in windows ([#303](https://github.com/mfontanini/presenterm/issues/303)).
* Add support for hidden lines in code snippets ([#283](https://github.com/mfontanini/presenterm/issues/283)) ([#254](https://github.com/mfontanini/presenterm/issues/254)) - thanks @dmackdev.
* Support [mermaid](https://mermaid.js.org/) snippet rendering to image via `+render` attribute ([#268](https://github.com/mfontanini/presenterm/issues/268)).
* Allow scaling images dynamically based on terminal size ([#288](https://github.com/mfontanini/presenterm/issues/288)) ([#291](https://github.com/mfontanini/presenterm/issues/291)).
* Allow scaling images generated via `+render` code blocks (mermaid, typst, latex) ([#290](https://github.com/mfontanini/presenterm/issues/290)).
* Show `stderr` output from code execution ([#252](https://github.com/mfontanini/presenterm/issues/252)) - thanks @dmackdev.
* Wait for code execution process to exit completely ([#250](https://github.com/mfontanini/presenterm/issues/250)) - thanks @dmackdev.
* Generate images in `+render` code snippets asynchronously ([#273](https://github.com/mfontanini/presenterm/issues/273)) ([#293](https://github.com/mfontanini/presenterm/issues/293)) ([#284](https://github.com/mfontanini/presenterm/issues/284)) ([#279](https://github.com/mfontanini/presenterm/issues/279)).
* Dim non highlighted code snippet lines ([#287](https://github.com/mfontanini/presenterm/issues/287)).
* Shrink snippet execution to match code block width ([#286](https://github.com/mfontanini/presenterm/issues/286)).
* Include code snippet execution output in generated PDF ([#295](https://github.com/mfontanini/presenterm/issues/295)).
* Cache `+render` block images ([#270](https://github.com/mfontanini/presenterm/issues/270)).
* Add kotlin script executor ([#257](https://github.com/mfontanini/presenterm/issues/257)) - thanks @dmackdev.
* Add nushell code execution ([#274](https://github.com/mfontanini/presenterm/issues/274)) ([#275](https://github.com/mfontanini/presenterm/issues/275)) - thanks @PitiBouchon.
* Add rust-script as a new code executor ([#269](https://github.com/mfontanini/presenterm/issues/269)) - @ZhangHanDong. 
* Allow custom themes to extend others ([#265](https://github.com/mfontanini/presenterm/issues/265)).
* Allow jumping fast between slides ([#244](https://github.com/mfontanini/presenterm/issues/244)).
* Allow explicitly disabling footer in certain slides ([#239](https://github.com/mfontanini/presenterm/issues/239)).
* Allow using image paths in typst ([#235](https://github.com/mfontanini/presenterm/issues/235)).
* Add JSON schema for validation,completion,documentation ([#228](https://github.com/mfontanini/presenterm/issues/228)) ([#236](https://github.com/mfontanini/presenterm/issues/236)) - thanks @mikavilpas.
* Allow having multiple authors ([#227](https://github.com/mfontanini/presenterm/issues/227)).

## Fixes

* Avoid re-rendering code output and auto rendered blocks ([#280](https://github.com/mfontanini/presenterm/issues/280)).
* Use unicode width to calculate execution output's line len ([#261](https://github.com/mfontanini/presenterm/issues/261)).
* Display background color behind '\t' in code exec output ([#245](https://github.com/mfontanini/presenterm/issues/245)).
* Close child process stdin by default ([#297](https://github.com/mfontanini/presenterm/issues/297)).

## Improvements

* Update install instructions for Arch Linux ([#248](https://github.com/mfontanini/presenterm/issues/248)) - thanks @orhun.
* Fix all clippy warnings ([#231](https://github.com/mfontanini/presenterm/issues/231)) - thanks @mikavilpas.
* Include strict `_front_matter_parsing` in default config ([#229](https://github.com/mfontanini/presenterm/issues/229)) - thanks @mikavilpas.
* `CHANGELOG.md` contains clickable links to issues ([#230](https://github.com/mfontanini/presenterm/issues/230)) - thanks @mikavilpas.
* Add Support for Ruby Code Highlighting ([#226](https://github.com/mfontanini/presenterm/issues/226)) - thanks @pranavrao145.
* Use ".presenterm" as prefix for tmp files ([#306](https://github.com/mfontanini/presenterm/issues/306)).
* Add more descriptive error message when loading image fails ([#298](https://github.com/mfontanini/presenterm/issues/298)).
* Align all error messages to left ([#301](https://github.com/mfontanini/presenterm/issues/301)).

# v0.7.0 - 2024-03-02

## New features

* Add color to prefix in block quote ([#218](https://github.com/mfontanini/presenterm/issues/218)).
* Allow having code blocks without background ([#215](https://github.com/mfontanini/presenterm/issues/215) [#216](https://github.com/mfontanini/presenterm/issues/216)).
* Allow validating whether presentation overflows terminal ([#209](https://github.com/mfontanini/presenterm/issues/209) [#211](https://github.com/mfontanini/presenterm/issues/211)).
* Add parameter to list themes ([#207](https://github.com/mfontanini/presenterm/issues/207)).
* Add catppuccin themes ([#197](https://github.com/mfontanini/presenterm/issues/197) [#205](https://github.com/mfontanini/presenterm/issues/205) [#206](https://github.com/mfontanini/presenterm/issues/206)) - thanks @Mawdac.
* Detect konsole terminal emulator ([#204](https://github.com/mfontanini/presenterm/issues/204)).
* Allow customizing slide title style ([#201](https://github.com/mfontanini/presenterm/issues/201)).

## Fixes

* Don't crash in present mode ([#210](https://github.com/mfontanini/presenterm/issues/210)).
* Set colors properly before displaying an error ([#212](https://github.com/mfontanini/presenterm/issues/212)).

## Improvements

* Suggest a tool is missing when spawning returns ENOTFOUND ([#221](https://github.com/mfontanini/presenterm/issues/221)).
* Sort input file list ([#202](https://github.com/mfontanini/presenterm/issues/202)) - thanks @bmwiedemann.
* Add more example presentations ([#217](https://github.com/mfontanini/presenterm/issues/217)).
* Add Scoop to package managers ([#200](https://github.com/mfontanini/presenterm/issues/200)) - thanks @nagromc.
* Remove support for uncommon image formats ([#208](https://github.com/mfontanini/presenterm/issues/208)).

# v0.6.1 - 2024-02-11

## Fixes

* Don't escape symbols in block quotes ([#195](https://github.com/mfontanini/presenterm/issues/195)).
* Respect `XDG_CONFIG_HOME` when loading configuration files and custom themes ([#193](https://github.com/mfontanini/presenterm/issues/193)).

# v0.6.0 - 2024-02-09

## Breaking changes

* The default configuration file and custom themes paths have been changed in Windows and macOS to be compliant to where 
  those platforms store these types of files. See the [configuration 
  guide](https://mfontanini.github.io/presenterm/guides/configuration.html) to learn more.

## New features

* Add `f` keys, tab, and backspace as possible bindings ([#188](https://github.com/mfontanini/presenterm/issues/188)).
* Add support for multiline block quotes ([#184](https://github.com/mfontanini/presenterm/issues/184)).
* Use theme color as background on ascii-blocks mode images ([#182](https://github.com/mfontanini/presenterm/issues/182)).
* Blend ascii-blocks image semi-transparent borders ([#185](https://github.com/mfontanini/presenterm/issues/185)).
* Respect Windows/macOS config paths for configuration ([#181](https://github.com/mfontanini/presenterm/issues/181)).
* Allow making front matter strict parsing optional ([#190](https://github.com/mfontanini/presenterm/issues/190)).

## Fixes

* Don't add an extra line after an end slide shorthand ([#187](https://github.com/mfontanini/presenterm/issues/187)).
* Don't clear input state on key release event ([#183](https://github.com/mfontanini/presenterm/issues/183)).

# v0.5.0 - 2024-01-26

## New features

* Support images on Windows ([#120](https://github.com/mfontanini/presenterm/issues/120)).
* Support animated gifs on kitty terminal ([#157](https://github.com/mfontanini/presenterm/issues/157) [#161](https://github.com/mfontanini/presenterm/issues/161)).
* Support images on tmux running in kitty terminal ([#166](https://github.com/mfontanini/presenterm/issues/166)).
* Improve sixel support ([#169](https://github.com/mfontanini/presenterm/issues/169) [#172](https://github.com/mfontanini/presenterm/issues/172)).
* Use synchronized updates to remove flickering when switching slides ([#156](https://github.com/mfontanini/presenterm/issues/156)).
* Add newlines command ([#167](https://github.com/mfontanini/presenterm/issues/167)).
* Detect image protocol instead of relying on viuer ([#160](https://github.com/mfontanini/presenterm/issues/160)).
* Turn documentation into mdbook ([#141](https://github.com/mfontanini/presenterm/issues/141) [#147](https://github.com/mfontanini/presenterm/issues/147)) - thanks @pwnwriter.
* Allow using thematic breaks to end slides ([#138](https://github.com/mfontanini/presenterm/issues/138)).
* Allow specifying the preferred image protocol via `--image-protocol` / config file ([#136](https://github.com/mfontanini/presenterm/issues/136) [#170](https://github.com/mfontanini/presenterm/issues/170)).
* Add slide index modal ([#128](https://github.com/mfontanini/presenterm/issues/128) [#139](https://github.com/mfontanini/presenterm/issues/139) [#133](https://github.com/mfontanini/presenterm/issues/133) [#158](https://github.com/mfontanini/presenterm/issues/158)).
* Allow defining custom keybindings in config file ([#132](https://github.com/mfontanini/presenterm/issues/132) [#155](https://github.com/mfontanini/presenterm/issues/155)).
* Add key bindings modal ([#152](https://github.com/mfontanini/presenterm/issues/152)).
* Prioritize CLI args `--theme` over anything else ([#116](https://github.com/mfontanini/presenterm/issues/116)).
* Allow enabling automatic list pauses ([#106](https://github.com/mfontanini/presenterm/issues/106) [#109](https://github.com/mfontanini/presenterm/issues/109) [#110](https://github.com/mfontanini/presenterm/issues/110)).
* Allow passing in config file path via CLI arg ([#174](https://github.com/mfontanini/presenterm/issues/174)).

## Fixes

* Shrink columns layout dimensions correctly when shrinking left ([#113](https://github.com/mfontanini/presenterm/issues/113)).
* Explicitly set execution output foreground color in built-in themes ([#122](https://github.com/mfontanini/presenterm/issues/122)).
* Detect sixel early and fallback to ascii blocks properly ([#135](https://github.com/mfontanini/presenterm/issues/135)).
* Exit with a clap error on missing path ([#150](https://github.com/mfontanini/presenterm/issues/150)).
* Don't blow up if presentation file temporarily disappears ([#154](https://github.com/mfontanini/presenterm/issues/154)).
* Parse front matter properly in presence of \r\n ([#162](https://github.com/mfontanini/presenterm/issues/162)).
* Don't preload graphics mode when generating pdf metadata ([#168](https://github.com/mfontanini/presenterm/issues/168)).
* Ignore key release events ([#119](https://github.com/mfontanini/presenterm/issues/119)).

## Improvements

* Validate that config file contains the right attributes ([#107](https://github.com/mfontanini/presenterm/issues/107)).
* Display first presentation load error as any other ([#118](https://github.com/mfontanini/presenterm/issues/118)).
* Add hashes for windows artifacts ([#126](https://github.com/mfontanini/presenterm/issues/126)).
* Remove arch packaging files ([#111](https://github.com/mfontanini/presenterm/issues/111)).
* Lower CPU and memory usage when displaying images ([#157](https://github.com/mfontanini/presenterm/issues/157)).

# v0.4.1 - 2023-12-22

## New features

* Cause an error if an unknown field name is found on a theme, config file, or front matter ([#102](https://github.com/mfontanini/presenterm/issues/102)).

## Fixes

* Explicitly disable kitty/iterm protocols when printing images in export PDF mode as this was causing PDF generation in 
  macOS to fail ([#101](https://github.com/mfontanini/presenterm/issues/101)).

# v0.4.0 - 2023-12-16

## New features

* Add support for all of [bat](https://github.com/sharkdp/bat)'s code highlighting themes ([#67](https://github.com/mfontanini/presenterm/issues/67)).
* Add `terminal-dark` and `terminal-light` themes that preserve the terminal's colors and background ([#68](https://github.com/mfontanini/presenterm/issues/68) [#69](https://github.com/mfontanini/presenterm/issues/69)).
* Allow placing themes in `$HOME/.config/presenterm/themes` to make them available automatically as if they were 
  built-in themes ([#73](https://github.com/mfontanini/presenterm/issues/73)).
* Allow configuring the default theme in `$HOME/.config/presenterm/config.yaml` ([#74](https://github.com/mfontanini/presenterm/issues/74)).
* Add support for rendering _LaTeX_ and _typst_ code blocks automatically as images ([#75](https://github.com/mfontanini/presenterm/issues/75) [#76](https://github.com/mfontanini/presenterm/issues/76) [#79](https://github.com/mfontanini/presenterm/issues/79) [#81](https://github.com/mfontanini/presenterm/issues/81)).
* Add syntax highlighting support for _nix_ and _diff_ ([#78](https://github.com/mfontanini/presenterm/issues/78) [#82](https://github.com/mfontanini/presenterm/issues/82)).
* Add comment command to jump into the middle of a slide ([#86](https://github.com/mfontanini/presenterm/issues/86)).
* Add configuration option to have implicit slide ends ([#87](https://github.com/mfontanini/presenterm/issues/87) [#89](https://github.com/mfontanini/presenterm/issues/89)).
* Add configuration option to have custom comment-command prefix ([#91](https://github.com/mfontanini/presenterm/issues/91)).

# v0.3.0 - 2023-11-24

## New features

* Support more languages in code blocks thanks to [bat](https://github.com/sharkdp/bat)'s syntax sets ([#21](https://github.com/mfontanini/presenterm/issues/21) [#53](https://github.com/mfontanini/presenterm/issues/53)).
* Add shell script executable code blocks ([#17](https://github.com/mfontanini/presenterm/issues/17)).
* Allow exporting presentation to PDF ([#43](https://github.com/mfontanini/presenterm/issues/43) [#60](https://github.com/mfontanini/presenterm/issues/60)).
* Pauses no longer create new slides ([#18](https://github.com/mfontanini/presenterm/issues/18) [#25](https://github.com/mfontanini/presenterm/issues/25) [#34](https://github.com/mfontanini/presenterm/issues/34) [#42](https://github.com/mfontanini/presenterm/issues/42)).
* Allow display code block line numbers ([#46](https://github.com/mfontanini/presenterm/issues/46)).
* Allow code block selective line highlighting ([#48](https://github.com/mfontanini/presenterm/issues/48)).
* Allow code block dynamic line highlighting ([#49](https://github.com/mfontanini/presenterm/issues/49)).
* Support animated gifs when using the iterm2 image protocol ([#56](https://github.com/mfontanini/presenterm/issues/56)).
* Nix flake packaging ([#11](https://github.com/mfontanini/presenterm/issues/11) [#27](https://github.com/mfontanini/presenterm/issues/27)).
* Arch repo packaging ([#10](https://github.com/mfontanini/presenterm/issues/10)).
* Ignore vim-like code folding tags in comments.
* Add keybinding to refresh assets in presentation ([#38](https://github.com/mfontanini/presenterm/issues/38)).
* Template style footer is now one row above bottom ([#39](https://github.com/mfontanini/presenterm/issues/39)).
* Add `light` theme.

## Fixes

* Don't crash on Windows when terminal window size can't be found ([#14](https://github.com/mfontanini/presenterm/issues/14)).
* Don't reset numbers on ordered lists when using pauses in between ([#19](https://github.com/mfontanini/presenterm/issues/19)).
* Show proper line number when parsing a comment command fails ([#29](https://github.com/mfontanini/presenterm/issues/29) [#40](https://github.com/mfontanini/presenterm/issues/40)).
* Don't reset the default footer when overriding theme in presentation without setting footer ([#52](https://github.com/mfontanini/presenterm/issues/52)).
* Don't let code blocks/block quotes that don't fit on the screen cause images to overlap with text ([#57](https://github.com/mfontanini/presenterm/issues/57)).

# v0.2.1 - 2023-10-18

## New features

* Binary artifacts are now automatically generated when a new release is done ([#5](https://github.com/mfontanini/presenterm/issues/5)) - thanks @pwnwriter.

# v0.2.0 - 2023-10-17

## New features

* [Column layouts](https://github.com/mfontanini/presenterm/blob/26e2eb28884675aac452f4c6e03f98413654240c/docs/layouts.md) that let you structure slides into columns.
* Support for `percent` margin rather than only a fixed number of columns.
* Spacebar now moves the presentation into the next slide.
* Add support for `center` footer when using the `template` mode.
* **Breaking**: themes now only use colors in hex format.

## Fixes

* Allow using `sh` as language for code block ([#3](https://github.com/mfontanini/presenterm/issues/3)).
* Minimum size for code blocks is now prioritized over minimum margin.
* Overflowing lines in lists will now correctly be padded to align all text under the same starting column.
* Running `cargo run` will now rebuild the tool if any of the built-in themes changed.
* `alignment` was removed from certain elements (like `list`) as it didn't really make sense.
* `default.alignment` is now no longer supported and by default we use left alignment. Use `default.margin` to specify the margins to use.

# v0.1.0 - 2023-10-08

## Features
* Define your presentation in a single markdown file.
* Image rendering support for iterm2, terminals that support the kitty graphics protocol, or sixel.
* Customize your presentation's look by defining themes, including colors, margins, layout (left/center aligned 
  content), footer for every slide, etc.
* Code highlighting for a wide list of programming languages.
* Support for an introduction slide that displays the presentation title and your name.
* Support for slide titles.
* Create pauses in between each slide so that it progressively renders for a more interactive presentation.
* Text formatting support for **bold**, _italics_, ~strikethrough~, and `inline code`.
* Automatically reload your presentation every time it changes for a fast development loop.


================================================
FILE: Cargo.toml
================================================
[package]
name = "presenterm"
authors = ["Matias Fontanini"]
description = "A terminal slideshow presentation tool"
repository = "https://github.com/mfontanini/presenterm"
license = "BSD-2-Clause"
version = "0.16.1"
edition = "2021"

[dependencies]
anyhow = "1"
base64 = "0.22"
bincode = "1.3"
clap = { version = "4.4", features = ["derive", "string", "env"] }
comrak = { version = "0.48.0", default-features = false }
crossterm = { version = "0.29", default-features = false, features = ["events", "windows"] }
directories = "6.0"
hex = "0.4"
fastrand = "2.3"
flate2 = "1.0"
image = { version = "0.25", features = ["gif", "jpeg", "png"], default-features = false }
icy_sixel = "0.5"
merge-struct = "0.1.0"
itertools = "0.14"
once_cell = "1.19"
portable-pty = "0.9"
schemars = { version = "0.8", optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
serde_json = "1.0"
syntect = { version = "5.2", features = ["parsing", "default-themes", "regex-onig", "plist-load"], default-features = false }
socket2 = "0.6"
strum = { version = "0.27", features = ["derive"] }
tempfile = { version = "3.10", default-features =  false }
tl = "0.7"
thiserror = "2"
unicode-width = "0.2"
os_pipe = "1.1.5"
libc = "0.2"
vte = "0.15"
termbg = "0.6.2"
vt100 = "0.16"

[dev-dependencies]
rstest = { version = "0.26", default-features = false }

[features]
default = []
json-schema = ["dep:schemars"]

[profile.dev]
opt-level = 0
debug = true
panic = "abort"

[profile.test]
opt-level = 0
debug = true

[profile.release]
opt-level = 3
debug = false
panic = "unwind"
lto = true
codegen-units = 1

[profile.bench]
opt-level = 3
debug = false


================================================
FILE: LICENSE
================================================
BSD 2-Clause License

Copyright (c) 2023, Matias Fontanini
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README.md
================================================
presenterm
===

[![crates-badge]][crates-package] [![brew-badge]][brew-package] [![nix-badge]][nix-package] 
[![arch-badge]][arch-package] [![scoop-badge]][scoop-package] [![winget-badge]][winget-package]

[brew-badge]: https://img.shields.io/homebrew/v/presenterm
[brew-package]: https://formulae.brew.sh/formula/presenterm
[nix-badge]: https://img.shields.io/badge/Packaged_for-Nix-5277C3.svg?logo=nixos&labelColor=73C3D5
[nix-package]: https://search.nixos.org/packages?size=1&show=presenterm
[crates-badge]: https://img.shields.io/crates/v/presenterm
[crates-package]: https://crates.io/crates/presenterm
[arch-badge]: https://img.shields.io/archlinux/v/extra/x86_64/presenterm
[arch-package]: https://archlinux.org/packages/extra/x86_64/presenterm/
[scoop-badge]: https://img.shields.io/scoop/v/presenterm
[scoop-package]: https://scoop.sh/#/apps?q=presenterm&id=a462290f824b50f180afbaa6d8c7c1e6e0952e3a
[winget-badge]: https://img.shields.io/winget/v/mfontanini.presenterm
[winget-package]: https://winstall.app/apps/mfontanini.presenterm

_presenterm_ lets you create presentations in markdown format and run them from your terminal, with support for image 
and animated gifs, highly customizable themes, code highlighting, exporting presentations into PDF format, and plenty of 
other features. This is how the [demo presentation](/examples/demo.md) looks like when running in the [kitty 
terminal](https://sw.kovidgoyal.net/kitty/):

![](/docs/src/assets/demo.gif)

Check the rest of the example presentations in the [examples directory](/examples).

# Documentation

Visit the [documentation][docs-introduction] to get started.

# Features

* Presentations consist of one [or more][docs-include] markdown files.
* [Images and animated gifs][docs-images] on terminals like _kitty_, _iterm2_, _wezterm_, _ghostty_ and _foot_.
* [Customizable themes][docs-themes] including colors, margins, layout (left/center aligned content), footer for every 
  slide, etc. Several [built-in themes][docs-builtin-themes] can give your presentation the look you want without 
  having to define your own.
* Code highlighting for a [wide list of programming languages][docs-code-highlight].
* [Font sizes][docs-font-sizes] for terminals that support them.
* [Selective/dynamic][docs-selective-highlight] code highlighting that only highlights portions of code at a time.
* [Column layouts][docs-layout].
* [mermaid graph rendering][docs-mermaid].
* [d2 graph rendering][docs-d2].
* [_LaTeX_ and _typst_ formula rendering][docs-latex].
* [Introduction slide][docs-intro-slide] that displays the presentation title and your name.
* [Slide titles][docs-slide-titles].
* [Snippet execution][docs-code-execute] for various programming languages, including execution inside pseudo terminals.
* [Export presentations to PDF and HTML][docs-exports].
* [Slide transitions][docs-slide-transitions].
* [Pause][docs-pauses] portions of your slides.
* [Custom key bindings][docs-key-bindings].
* [Automatically reload your presentation][docs-hot-reload] every time it changes for a fast development loop.
* [Define speaker notes][docs-speaker-notes] to aid you during presentations.

See the [introduction page][docs-introduction] to learn more.

# presenterm in action

Here are some talks and demos that feature _presenterm_:

- [Bringing Terminal Aesthetics to the Web With Rust][bringing-terminal-aesthetics] by [Orhun Parmaksız][orhun-github]
- [7 Rust Terminal Tools That You Should Use][rust-terminal-tools] by [Orhun Parmaksız][orhun-github]
- [Renaissance of Terminal User Interfaces with Rust][renaissance-tui] by [Orhun Parmaksız][orhun-github]
- [Using Nix on Apple Silicon and declarative development environments][NiXOS-and-Dev] by [pwnwriter][pwnwriter-github]
- [Hayasen: A Robust Embedded Rust Library which supports multiple sensors][hayasen] by [Vaishnav-Sabari-Girish][vaishnav]
- [Using ratatui in Embedded sytems : Meet Mousefood][mousefood] by [Vaishnav-Sabari-Girish][vaishnav]

Gave a talk using _presenterm_? We would love to feature it here! Open a PR or issue to get it added.

<!-- links -->

[docs-introduction]: https://mfontanini.github.io/presenterm/
[docs-basics]: https://mfontanini.github.io/presenterm/features/introduction.html
[docs-intro-slide]: https://mfontanini.github.io/presenterm/features/introduction.html#introduction-slide
[docs-slide-titles]: https://mfontanini.github.io/presenterm/features/introduction.html#slide-titles
[docs-font-sizes]: https://mfontanini.github.io/presenterm/features/introduction.html#font-sizes
[docs-pauses]: https://mfontanini.github.io/presenterm/features/commands.html#pauses
[docs-images]: https://mfontanini.github.io/presenterm/features/images.html
[docs-include]: https://mfontanini.github.io/presenterm/features/commands.html#including-external-markdown-files
[docs-themes]: https://mfontanini.github.io/presenterm/features/themes/introduction.html
[docs-builtin-themes]: https://mfontanini.github.io/presenterm/features/themes/introduction.html#built-in-themes
[docs-code-highlight]: https://mfontanini.github.io/presenterm/features/code/highlighting.html
[docs-code-execute]: https://mfontanini.github.io/presenterm/features/code/execution.html
[docs-selective-highlight]: https://mfontanini.github.io/presenterm/features/code/highlighting.html#selective-highlighting
[docs-slide-transitions]: https://mfontanini.github.io/presenterm/features/slide-transitions.html
[docs-layout]: https://mfontanini.github.io/presenterm/features/layout.html
[docs-mermaid]: https://mfontanini.github.io/presenterm/features/code/mermaid.html
[docs-d2]: https://mfontanini.github.io/presenterm/features/code/d2.html
[docs-latex]: https://mfontanini.github.io/presenterm/features/code/latex.html
[docs-exports]: https://mfontanini.github.io/presenterm/features/exports.html
[docs-key-bindings]: https://mfontanini.github.io/presenterm/configuration/settings.html#key-bindings
[docs-hot-reload]: https://mfontanini.github.io/presenterm/features/introduction.html#hot-reload
[docs-speaker-notes]: https://mfontanini.github.io/presenterm/features/speaker-notes.html
[bat]: https://github.com/sharkdp/bat
[syntect]: https://github.com/trishume/syntect
[bringing-terminal-aesthetics]: https://www.youtube.com/watch?v=iepbyYrF_YQ
[rust-terminal-tools]: https://www.youtube.com/watch?v=ATiKwUiqnAU
[renaissance-tui]: https://www.youtube.com/watch?v=hWG51Mc1DlM
[orhun-github]: https://github.com/orhun
[NiXOS-and-Dev]: https://github.com/pwnwriter/PTN11
[pwnwriter-github]: https://github.com/pwnwriter
[hayasen]: https://github.com/Vaishnav-Sabari-Girish/rust_bangalore_oct_2025
[vaishnav]: https://github.com/Vaishnav-Sabari-Girish
[mousefood]: https://github.com/Vaishnav-Sabari-Girish/rust_bangalore_december_2025/


================================================
FILE: bat/bat.git-hash
================================================
0e469634a3e8987fd7085520e1f90cd83d8fe51b


================================================
FILE: bat/syntaxes.git-hash
================================================
3d87b25b190e0990e0e75a2ab8f994d6c277d263


================================================
FILE: bat/update.sh
================================================
#!/usr/bin/env bash

set -e

if [ $# -ne 1 ]; then
    echo "Usage: $0 <bat-git-hash>"
    exit 1
fi

script_path=$(realpath "$0")
script_dir=$(dirname "$script_path")
git_hash=$1
clone_path=$(mktemp -d)

echo "Cloning repo @ ${git_hash} into '$clone_path'"
git clone https://github.com/sharkdp/bat.git "$clone_path"
cd "$clone_path"
git reset --hard "$git_hash"

cp assets/syntaxes.bin "$script_dir"
cp assets/themes.bin "$script_dir"

acknowledgements_file="$script_dir/acknowledgements.txt"
cp LICENSE-MIT "$acknowledgements_file"
zlib-flate -uncompress <assets/acknowledgements.bin >>"$acknowledgements_file"
echo "$git_hash" >"$script_dir/bat.git-hash"

echo "syntaxes/themes updated"


================================================
FILE: bat/verify.sh
================================================
#!/usr/bin/env bash

set -e

script_path=$(realpath "$0")
script_dir=$(dirname "$script_path")
clone_path=$(mktemp -d)

git_hash=$(cat "$script_dir/bat.git-hash")
echo "Cloning repo @ ${git_hash} into '$clone_path'"
git clone https://github.com/sharkdp/bat.git "$clone_path"
cd "$clone_path"
git reset --hard "$git_hash"

for file in syntaxes.bin themes.bin; do
    our_hash=$(sha256sum "$script_dir/$file" | cut -d " " -f1)
    their_hash=$(sha256sum "$clone_path/assets/$file" | cut -d " " -f 1)
    if [ "$our_hash" != "$their_hash" ]; then
        echo "Unexpected hash for ${file}: should be ${their_hash}, is ${our_hash}"
        exit 1
    fi
done

echo "All hashes match"


================================================
FILE: build.rs
================================================
use std::{
    env,
    fs::{self, File},
    io::{self, BufWriter, Write},
};

// Take all files under `themes` and turn them into a file that contains a hashmap with their
// contents by name. This is pulled in theme.rs to construct themes.
fn build_themes(out_dir: &str) -> io::Result<()> {
    let output_path = format!("{out_dir}/themes.rs");
    let mut output_file = BufWriter::new(File::create(output_path)?);
    output_file.write_all(b"use std::collections::BTreeMap as Map;\n")?;
    output_file.write_all(b"use once_cell::sync::Lazy;\n")?;
    output_file.write_all(b"static THEMES: Lazy<Map<&'static str, &'static [u8]>> = Lazy::new(|| Map::from([\n")?;

    let mut paths = fs::read_dir("themes")?.collect::<io::Result<Vec<_>>>()?;
    paths.sort_by_key(|e| e.path());
    for theme_file in paths {
        let metadata = theme_file.metadata()?;
        if !metadata.is_file() {
            panic!("found non file in themes directory");
        }
        let path = theme_file.path();
        let contents = fs::read(&path)?;
        let file_name = path.file_name().unwrap().to_string_lossy();
        let theme_name = file_name.split_once('.').unwrap().0;
        // TODO this wastes a bit of space
        output_file.write_all(format!("(\"{theme_name}\", {contents:?}.as_slice()),\n").as_bytes())?;
    }
    output_file.write_all(b"]));\n")?;

    // Rebuild if anything changes.
    println!("cargo:rerun-if-changed=themes");
    Ok(())
}

fn main() -> io::Result<()> {
    let out_dir = env::var("OUT_DIR").unwrap();
    build_themes(&out_dir)?;
    Ok(())
}


================================================
FILE: config-file-schema.json
================================================
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Config",
  "type": "object",
  "properties": {
    "bindings": {
      "$ref": "#/definitions/KeyBindingsConfig"
    },
    "d2": {
      "$ref": "#/definitions/D2Config"
    },
    "defaults": {
      "description": "The default configuration for the presentation.",
      "allOf": [
        {
          "$ref": "#/definitions/DefaultsConfig"
        }
      ]
    },
    "export": {
      "$ref": "#/definitions/ExportConfig"
    },
    "mermaid": {
      "$ref": "#/definitions/MermaidConfig"
    },
    "options": {
      "$ref": "#/definitions/OptionsConfig"
    },
    "snippet": {
      "$ref": "#/definitions/SnippetConfig"
    },
    "speaker_notes": {
      "$ref": "#/definitions/SpeakerNotesConfig"
    },
    "transition": {
      "anyOf": [
        {
          "$ref": "#/definitions/SlideTransitionConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "typst": {
      "$ref": "#/definitions/TypstConfig"
    }
  },
  "additionalProperties": false,
  "definitions": {
    "D2Config": {
      "type": "object",
      "properties": {
        "scale": {
          "description": "The scaling parameter to be used in the d2 CLI.",
          "default": null,
          "type": [
            "number",
            "null"
          ],
          "format": "float"
        }
      },
      "additionalProperties": false
    },
    "DefaultsConfig": {
      "type": "object",
      "properties": {
        "image_protocol": {
          "description": "The image protocol to use.",
          "allOf": [
            {
              "$ref": "#/definitions/ImageProtocol"
            }
          ]
        },
        "incremental_lists": {
          "description": "The configuration for lists when incremental lists are enabled.",
          "allOf": [
            {
              "$ref": "#/definitions/IncrementalElementConfig"
            }
          ]
        },
        "incremental_tables": {
          "description": "The configuration for tables when incremental tables are enabled.",
          "allOf": [
            {
              "$ref": "#/definitions/IncrementalElementConfig"
            }
          ]
        },
        "max_columns": {
          "description": "A max width in columns that the presentation must always be capped to.",
          "default": 65535,
          "type": "integer",
          "format": "uint16",
          "minimum": 0.0
        },
        "max_columns_alignment": {
          "description": "The alignment the presentation should have if `max_columns` is set and the terminal is larger than that.",
          "allOf": [
            {
              "$ref": "#/definitions/MaxColumnsAlignment"
            }
          ]
        },
        "max_rows": {
          "description": "A max height in rows that the presentation must always be capped to.",
          "default": 65535,
          "type": "integer",
          "format": "uint16",
          "minimum": 0.0
        },
        "max_rows_alignment": {
          "description": "The alignment the presentation should have if `max_rows` is set and the terminal is larger than that.",
          "allOf": [
            {
              "$ref": "#/definitions/MaxRowsAlignment"
            }
          ]
        },
        "terminal_font_size": {
          "description": "Override the terminal font size when in windows or when using sixel.",
          "default": 16,
          "type": "integer",
          "format": "uint8",
          "minimum": 1.0
        },
        "theme": {
          "description": "The theme to use by default in every presentation unless overridden.",
          "allOf": [
            {
              "$ref": "#/definitions/ThemeConfig"
            }
          ]
        },
        "validate_overflows": {
          "description": "Validate that the presentation does not overflow the terminal screen.",
          "allOf": [
            {
              "$ref": "#/definitions/ValidateOverflows"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ExportConfig": {
      "description": "The export configuration.",
      "type": "object",
      "properties": {
        "dimensions": {
          "description": "The dimensions to use for presentation exports.",
          "anyOf": [
            {
              "$ref": "#/definitions/ExportDimensionsConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "pauses": {
          "description": "Whether pauses should create new slides.",
          "allOf": [
            {
              "$ref": "#/definitions/PauseExportPolicy"
            }
          ]
        },
        "pdf": {
          "description": "The PDF specific export configs.",
          "allOf": [
            {
              "$ref": "#/definitions/PdfExportConfig"
            }
          ]
        },
        "snippets": {
          "description": "The policy for executable snippets when exporting.",
          "allOf": [
            {
              "$ref": "#/definitions/SnippetsExportPolicy"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ExportDimensionsConfig": {
      "description": "The dimensions to use for presentation exports.",
      "type": "object",
      "required": [
        "columns",
        "rows"
      ],
      "properties": {
        "columns": {
          "description": "The number of columns.",
          "type": "integer",
          "format": "uint16",
          "minimum": 0.0
        },
        "rows": {
          "description": "The number of rows.",
          "type": "integer",
          "format": "uint16",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    "ExportFontsConfig": {
      "description": "The fonts used for exports.",
      "type": "object",
      "required": [
        "normal"
      ],
      "properties": {
        "bold": {
          "description": "The path to the font file to be used for the \"bold\" variable of this font.",
          "type": [
            "string",
            "null"
          ]
        },
        "bold_italic": {
          "description": "The path to the font file to be used for the \"bold+italic\" variable of this font.",
          "type": [
            "string",
            "null"
          ]
        },
        "italic": {
          "description": "The path to the font file to be used for the \"italic\" variable of this font.",
          "type": [
            "string",
            "null"
          ]
        },
        "normal": {
          "description": "The path to the font file to be used for the \"normal\" variable of this font.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "ImageProtocol": {
      "oneOf": [
        {
          "description": "Automatically detect the best image protocol to use.",
          "type": "string",
          "enum": [
            "auto"
          ]
        },
        {
          "description": "Use the iTerm2 image protocol.",
          "type": "string",
          "enum": [
            "iterm2"
          ]
        },
        {
          "description": "Use the iTerm2 image protocol in multipart mode.",
          "type": "string",
          "enum": [
            "iterm2-multipart"
          ]
        },
        {
          "description": "Use the kitty protocol in \"local\" mode, meaning both presenterm and the terminal run in the same host and can share the filesystem to communicate.",
          "type": "string",
          "enum": [
            "kitty-local"
          ]
        },
        {
          "description": "Use the kitty protocol in \"remote\" mode, meaning presenterm and the terminal run in different hosts and therefore can only communicate via terminal escape codes.",
          "type": "string",
          "enum": [
            "kitty-remote"
          ]
        },
        {
          "description": "Use the sixel protocol.",
          "type": "string",
          "enum": [
            "sixel"
          ]
        },
        {
          "description": "The default image protocol to use when no other is specified.",
          "type": "string",
          "enum": [
            "ascii-blocks"
          ]
        }
      ]
    },
    "IncrementalElementConfig": {
      "description": "The configuration for incrementally shown elements.",
      "type": "object",
      "properties": {
        "pause_after": {
          "description": "Whether to pause after.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "pause_before": {
          "description": "Whether to pause before.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "KeyBinding": {
      "type": "string"
    },
    "KeyBindingsConfig": {
      "type": "object",
      "properties": {
        "close_modal": {
          "description": "The key binding to close the currently open modal.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "execute_code": {
          "description": "The key binding to execute a piece of shell code.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "exit": {
          "description": "The key binding to close the application.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "first_slide": {
          "description": "The key binding to jump to the first slide.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "go_to_slide": {
          "description": "The key binding to jump to a specific slide.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "last_slide": {
          "description": "The key binding to jump to the last slide.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "next": {
          "description": "The keys that cause the presentation to move forwards.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "next_fast": {
          "description": "The keys that cause the presentation to jump to the next slide \"fast\".\n\n\"fast\" means for slides that contain pauses, we will skip all pauses and jump straight to the next slide.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "previous": {
          "description": "The keys that cause the presentation to move backwards.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "previous_fast": {
          "description": "The keys that cause the presentation to move backwards \"fast\".\n\n\"fast\" means for slides that contain pauses, we will skip all pauses and jump straight to the previous slide.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "reload": {
          "description": "The key binding to reload the presentation.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "skip_pauses": {
          "description": "The key binding to show the entire slide, after skipping any pauses in it.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "suspend": {
          "description": "The key binding to suspend the application.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "toggle_bindings": {
          "description": "The key binding to toggle the key bindings modal.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "toggle_layout_grid": {
          "description": "The key binding to toggle the layout grid.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        },
        "toggle_slide_index": {
          "description": "The key binding to toggle the slide index modal.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyBinding"
          }
        }
      },
      "additionalProperties": false
    },
    "LanguageSnippetExecutionConfig": {
      "description": "The snippet execution configuration for a specific programming language.",
      "type": "object",
      "required": [
        "commands",
        "filename"
      ],
      "properties": {
        "alternative": {
          "description": "Alternative executors for this language.",
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/SnippetExecutorConfig"
          }
        },
        "commands": {
          "description": "The commands to be ran when executing snippets for this programming language.",
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "environment": {
          "description": "The environment variables to set before invoking every command.",
          "default": {},
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "filename": {
          "description": "The filename to use for the snippet input file.",
          "type": "string"
        },
        "hidden_line_prefix": {
          "description": "The prefix to use to hide lines visually but still execute them.",
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "MaxColumnsAlignment": {
      "description": "The alignment to use when `defaults.max_columns` is set.",
      "oneOf": [
        {
          "description": "Align the presentation to the left.",
          "type": "string",
          "enum": [
            "left"
          ]
        },
        {
          "description": "Align the presentation on the center.",
          "type": "string",
          "enum": [
            "center"
          ]
        },
        {
          "description": "Align the presentation to the right.",
          "type": "string",
          "enum": [
            "right"
          ]
        }
      ]
    },
    "MaxRowsAlignment": {
      "description": "The alignment to use when `defaults.max_rows` is set.",
      "oneOf": [
        {
          "description": "Align the presentation to the top.",
          "type": "string",
          "enum": [
            "top"
          ]
        },
        {
          "description": "Align the presentation on the center.",
          "type": "string",
          "enum": [
            "center"
          ]
        },
        {
          "description": "Align the presentation to the bottom.",
          "type": "string",
          "enum": [
            "bottom"
          ]
        }
      ]
    },
    "MermaidConfig": {
      "type": "object",
      "properties": {
        "config_path": {
          "description": "A path to a mermaid JSON configuration file to be used by the `mmdc` tool.",
          "type": [
            "string",
            "null"
          ]
        },
        "puppeteer_config_path": {
          "description": "A path to a puppeteer JSON configuration file to be used by the `mmdc` tool.",
          "type": [
            "string",
            "null"
          ]
        },
        "scale": {
          "description": "The scaling parameter to be used in the mermaid CLI.",
          "default": 2,
          "type": "integer",
          "format": "uint32",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    "OptionsConfig": {
      "type": "object",
      "properties": {
        "auto_render_languages": {
          "description": "Assume snippets for these languages contain `+render` and render them automatically.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/SnippetLanguage"
          }
        },
        "command_prefix": {
          "description": "The prefix to use for commands.",
          "type": [
            "string",
            "null"
          ]
        },
        "end_slide_shorthand": {
          "description": "Whether to treat a thematic break as a slide end.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "h1_slide_titles": {
          "description": "Whether the first `h1` header on a slide should be considered a slide title.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "image_attributes_prefix": {
          "description": "The prefix to use for image attributes.",
          "type": [
            "string",
            "null"
          ]
        },
        "implicit_slide_ends": {
          "description": "Whether slides are automatically terminated when a slide title is found.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "incremental_lists": {
          "description": "Show all lists incrementally, by implicitly adding pauses in between elements.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "incremental_tables": {
          "description": "Show all tables incrementally, by implicitly adding pauses in between rows.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "list_item_newlines": {
          "description": "The number of newlines in between list items.",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint8",
          "minimum": 1.0
        },
        "strict_front_matter_parsing": {
          "description": "Whether to be strict about parsing the presentation's front matter.",
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "PauseExportPolicy": {
      "description": "The policy for pauses when exporting.",
      "oneOf": [
        {
          "description": "Whether to ignore pauses.",
          "type": "string",
          "enum": [
            "ignore"
          ]
        },
        {
          "description": "Create a new slide when a pause is found.",
          "type": "string",
          "enum": [
            "new_slide"
          ]
        }
      ]
    },
    "PdfExportConfig": {
      "description": "The PDF export specific configs.",
      "type": "object",
      "properties": {
        "fonts": {
          "description": "The path to the font file to be used.",
          "anyOf": [
            {
              "$ref": "#/definitions/ExportFontsConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "SlideTransitionConfig": {
      "type": "object",
      "required": [
        "animation"
      ],
      "properties": {
        "animation": {
          "description": "The slide transition style.",
          "allOf": [
            {
              "$ref": "#/definitions/SlideTransitionStyleConfig"
            }
          ]
        },
        "duration_millis": {
          "description": "The amount of time to take to perform the transition.",
          "default": 1000,
          "type": "integer",
          "format": "uint16",
          "minimum": 0.0
        },
        "frames": {
          "description": "The number of frames in a transition.",
          "default": 30,
          "type": "integer",
          "format": "uint",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    "SlideTransitionStyleConfig": {
      "oneOf": [
        {
          "description": "Slide horizontally.",
          "type": "object",
          "required": [
            "style"
          ],
          "properties": {
            "style": {
              "type": "string",
              "enum": [
                "slide_horizontal"
              ]
            }
          },
          "additionalProperties": false
        },
        {
          "description": "Fade the new slide into the previous one.",
          "type": "object",
          "required": [
            "style"
          ],
          "properties": {
            "style": {
              "type": "string",
              "enum": [
                "fade"
              ]
            }
          },
          "additionalProperties": false
        },
        {
          "description": "Collapse the current slide into the center of the screen.",
          "type": "object",
          "required": [
            "style"
          ],
          "properties": {
            "style": {
              "type": "string",
              "enum": [
                "collapse_horizontal"
              ]
            }
          },
          "additionalProperties": false
        }
      ]
    },
    "SnippetConfig": {
      "type": "object",
      "properties": {
        "exec": {
          "description": "The properties for snippet execution.",
          "allOf": [
            {
              "$ref": "#/definitions/SnippetExecConfig"
            }
          ]
        },
        "exec_replace": {
          "description": "The properties for snippet execution.",
          "allOf": [
            {
              "$ref": "#/definitions/SnippetExecReplaceConfig"
            }
          ]
        },
        "render": {
          "description": "The properties for snippet auto rendering.",
          "allOf": [
            {
              "$ref": "#/definitions/SnippetRenderConfig"
            }
          ]
        },
        "validate": {
          "description": "Whether to validate snippets.",
          "default": false,
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "SnippetExecConfig": {
      "type": "object",
      "properties": {
        "custom": {
          "description": "Custom snippet executors.",
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/LanguageSnippetExecutionConfig"
          }
        },
        "enable": {
          "description": "Whether to enable snippet execution.",
          "default": false,
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "SnippetExecReplaceConfig": {
      "type": "object",
      "required": [
        "enable"
      ],
      "properties": {
        "enable": {
          "description": "Whether to enable snippet replace-executions, which automatically run code snippets without the user's intervention.",
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "SnippetExecutorConfig": {
      "description": "A snippet executor configuration.",
      "type": "object",
      "required": [
        "commands",
        "filename"
      ],
      "properties": {
        "commands": {
          "description": "The commands to be ran when executing snippets for this programming language.",
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "environment": {
          "description": "The environment variables to set before invoking every command.",
          "default": {},
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "filename": {
          "description": "The filename to use for the snippet input file.",
          "type": "string"
        }
      }
    },
    "SnippetLanguage": {
      "description": "The language of a code snippet.",
      "oneOf": [
        {
          "type": "string",
          "enum": [
            "Ada",
            "Asp",
            "Awk",
            "Bash",
            "BatchFile",
            "C",
            "CMake",
            "Crontab",
            "CSharp",
            "Clojure",
            "Cpp",
            "Css",
            "Dart",
            "D2",
            "DLang",
            "Diff",
            "Docker",
            "Dotenv",
            "Elixir",
            "Elm",
            "Erlang",
            "File",
            "Fish",
            "FSharp",
            "GdScript",
            "Go",
            "GraphQL",
            "Haskell",
            "Html",
            "Java",
            "JavaScript",
            "Json",
            "Jsonnet",
            "Julia",
            "Kotlin",
            "Latex",
            "Lua",
            "Makefile",
            "Mermaid",
            "Markdown",
            "Nix",
            "Nushell",
            "OCaml",
            "Perl",
            "Php",
            "PowerShell",
            "Protobuf",
            "Puppet",
            "Python",
            "R",
            "Racket",
            "Ruby",
            "Rust",
            "RustScript",
            "Scala",
            "Shell",
            "Sql",
            "Swift",
            "Svelte",
            "Tcl",
            "Terraform",
            "Toml",
            "TypeScript",
            "TypeScriptReact",
            "Typst",
            "Xml",
            "Yaml",
            "Verilog",
            "Vue",
            "Wsl",
            "Zig",
            "Zsh"
          ]
        },
        {
          "type": "object",
          "required": [
            "Unknown"
          ],
          "properties": {
            "Unknown": {
              "type": "string"
            }
          },
          "additionalProperties": false
        }
      ]
    },
    "SnippetRenderConfig": {
      "type": "object",
      "properties": {
        "threads": {
          "description": "The number of threads to use when rendering.",
          "default": 2,
          "type": "integer",
          "format": "uint",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    "SnippetsExportPolicy": {
      "description": "The policy for executable snippets when exporting.",
      "oneOf": [
        {
          "description": "Render all executable snippets in parallel.",
          "type": "string",
          "enum": [
            "parallel"
          ]
        },
        {
          "description": "Render all executable snippets sequentially.",
          "type": "string",
          "enum": [
            "sequential"
          ]
        }
      ]
    },
    "SpeakerNotesConfig": {
      "type": "object",
      "properties": {
        "always_publish": {
          "description": "Whether to always publish speaker notes.",
          "default": false,
          "type": "boolean"
        },
        "listen_address": {
          "description": "The address in which to listen for speaker note events.",
          "default": "127.255.255.255:59418",
          "type": "string"
        },
        "publish_address": {
          "description": "The address in which to publish speaker notes events.",
          "default": "127.255.255.255:59418",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "ThemeConfig": {
      "anyOf": [
        {
          "type": "null"
        },
        {
          "description": "Theme of the presentation.",
          "type": "string"
        },
        {
          "description": "Automatic dark/light theme switch based on the terminal background luminance.",
          "type": "object",
          "required": [
            "dark",
            "light"
          ],
          "properties": {
            "dark": {
              "description": "Dark theme of the presentation.",
              "type": "string"
            },
            "light": {
              "description": "Light theme of the presentation.",
              "type": "string"
            },
            "timeout": {
              "description": "Light/Dark detection timeout in ms.",
              "type": [
                "integer",
                "null"
              ],
              "format": "uint64",
              "minimum": 1.0
            }
          },
          "additionalProperties": false
        }
      ]
    },
    "TypstConfig": {
      "type": "object",
      "properties": {
        "ppi": {
          "description": "The pixels per inch when rendering latex/typst formulas.",
          "default": 300,
          "type": "integer",
          "format": "uint32",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    "ValidateOverflows": {
      "type": "string",
      "enum": [
        "never",
        "always",
        "when_presenting",
        "when_developing"
      ]
    }
  }
}

================================================
FILE: config.sample.yaml
================================================
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/mfontanini/presenterm/master/config-file-schema.json
defaults:
  # override the terminal font size when in windows or when using sixel.
  terminal_font_size: 16

  # the theme to use by default in every presentation unless overridden.
  theme: dark

  # the image protocol to use.
  image_protocol: kitty-local

typst:
  # the pixels per inch when rendering latex/typst formulas.
  ppi: 300

mermaid:
  # the scale parameter passed to the mermaid CLI (mmdc).
  scale: 2

options:
  # whether slides are automatically terminated when a slide title is found.
  implicit_slide_ends: false

  # the prefix to use for commands.
  command_prefix: ""

  # show all lists incrementally, by implicitly adding pauses in between elements.
  incremental_lists: false

  # this option tells presenterm you don't care about extra parameters in
  # presentation's front matter. This can be useful if you're trying to load a
  # presentation made for another tool
  strict_front_matter_parsing: true

  # whether to treat a thematic break as a slide end.
  end_slide_shorthand: false

snippet:
  exec:
    # enable code snippet execution. Use at your own risk!
    enable: true

  exec_replace:
    # enable code snippet automatic execution + replacing the snippet with its output. Use at your own risk!
    enable: true

  render:
    # the number of threads to use when rendering `+render` code snippets.
    threads: 2

speaker_notes:
  # The endpoint to listen for speaker note events.
  listen_address: "127.0.0.1:59418"

  # The endpoint to publish speaker note events.
  publish_address: "127.0.0.1:59418"

  # Whether to always publish speaker notes even when `--publish-speaker-notes` is not set.
  always_publish: false

bindings:
  # the keys that cause the presentation to move forwards.
  next: ["l", "j", "<right>", "<page_down>", "<down>", " "]

  # the keys that cause the presentation to move forwards fast.
  next_fast: ["n"]

  # the keys that cause the presentation to move backwards.
  previous: ["h", "k", "<left>", "<page_up>", "<up>"]

  # the keys that cause the presentation to move backwards fast
  previous_fast: ["p"]

  # the key binding to jump to the first slide.
  first_slide: ["gg"]

  # the key binding to jump to the last slide.
  last_slide: ["G"]

  # the key binding to jump to a specific slide.
  go_to_slide: ["<number>G"]

  # the key binding to execute a piece of shell code.
  execute_code: ["<c-e>"]

  # the key binding to reload the presentation.
  reload: ["<c-r>"]

  # the key binding to toggle the slide index modal.
  toggle_slide_index: ["<c-p>"]

  # the key binding to toggle the key bindings modal.
  toggle_bindings: ["?"]

  # the key binding to close the currently open modal.
  close_modal: ["<esc>"]

  # the key binding to close the application.
  exit: ["<c-c>", "q"]

  # the key binding to suspend the application.
  suspend: ["<c-z>"]

  # the key binding to skip all pauses in the current slide.
  skip_pauses: ["s"]


================================================
FILE: docs/.gitignore
================================================
book/


================================================
FILE: docs/book.toml
================================================
[book]
authors = ["mfontanini"]
language = "en"
multilingual = false
src = "src"
title = "presenterm documentation"

[preprocessor]

[preprocessor.alerts]

[output]

[output.html]
git-repository-url = "https://github.com/mfontanini/presenterm"
default-theme = "navy"

[output.html.redirect]
# Redirects for broken links after 02/02/2025 restructuring.
"/guides/basics.html" = "../features/introduction.html"
"/guides/installation.html" = "../install.html"
"/guides/code-highlight.html" = "../features/code/highlighting.html"
"/guides/mermaid.html" = "../features/code/mermaid.html"

# Redirects for HTML export changes on 05/17/2025.
"/features/pdf-export.html" = "exports.html"



================================================
FILE: docs/src/SUMMARY.md
================================================
# Summary

[Introduction](./introduction.md)

# Docs

- [Install](./install.md)
- [Features](./features/introduction.md)
    - [Images](./features/images.md).
    - [Commands](./features/commands.md).
    - [Layout](./features/layout.md).
    - [Code](./features/code/highlighting.md)
        - [Execution](./features/code/execution.md)
        - [Mermaid diagrams](./features/code/mermaid.md)
        - [LaTeX and typst](./features/code/latex.md)
        - [D2](./features/code/d2.md)
    - [Themes](./features/themes/introduction.md)
        - [Definition](./features/themes/definition.md)
    - [Exports](./features/exports.md)
    - [Slide transitions](./features/slide-transitions.md)
    - [Speaker notes](./features/speaker-notes.md)
- [Configuration](./configuration/introduction.md)
    - [Options](./configuration/options.md)
    - [Settings](./configuration/settings.md)

# Internals

- [Parse](./internals/parse.md)

---

[Acknowledgements](./acknowledgements.md)


================================================
FILE: docs/src/acknowledgements.md
================================================
## Acknowledgements

This tool is heavily inspired by:

* [slides][slides_url]
* [lookatme][lookatme_url]
* [sli.dev][slide_dev_url]

Support for code highlighting on many languages is thanks to [bat][bat_url], which contains a 
custom set of syntaxes that extend [syntect][syntect_url]'s default set of supported languages. 
Run `presenterm --acknowledgements` to get a full list of all the licenses for the binary files being pulled in.

## Contributors

Thanks to everyone who's contributed to _presenterm_ in one way or another! This is a list of the users who have 
contributed code to make _presenterm_ better in some way:

<a href="https://github.com/mfontanini/presenterm/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=mfontanini/presenterm" />
</a>

<!-- Links -->
[slides_url]: https://github.com/maaslalani/slides/
[lookatme_url]: https://github.com/d0c-s4vage/lookatme
[slide_dev_url]: https://sli.dev/
[bat_url]: https://github.com/sharkdp/bat
[syntect_url]: https://github.com/trishume/syntect


================================================
FILE: docs/src/configuration/introduction.md
================================================
# Configuration

_presenterm_ allows you to customize its behavior via a configuration file. This file is stored, along with all of your 
custom themes, in the following directories:

* `$XDG_CONFIG_HOME/presenterm/` if that environment variable is defined, otherwise:
* `~/.config/presenterm/` in Linux.
* `~/Library/Application Support/presenterm/` in macOS.
* `~/AppData/Roaming/presenterm/config/` in Windows.

The configuration file will be looked up automatically in the directories above under the name `config.yaml`. e.g. on 
Linux you should create it under `~/.config/presenterm/config.yaml`. You can also specify a custom path to this file 
when running _presenterm_ via the `--config-file` parameter or the `PRESENTERM_CONFIG_FILE` environment variable.

A [sample configuration file](https://github.com/mfontanini/presenterm/blob/master/config.sample.yaml) is provided in 
the repository that you can use as a base.

# Configuration schema

A JSON schema that defines the configuration file's schema is available to be used with YAML language servers such as
[yaml-language-server](https://github.com/redhat-developer/yaml-language-server).

Include the following line at the beginning of your configuration file to have your editor pull in autocompletion 
suggestions and docs automatically:

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/mfontanini/presenterm/master/config-file-schema.json
```


================================================
FILE: docs/src/configuration/options.md
================================================
# Options

Options are special configuration parameters that can be set either in the configuration file under the `options` key, 
or in a presentation's front matter under the same key. This last one allows you to customize a single presentation so 
that it acts in a particular way. This can also be useful if you'd like to share the source files for your presentation 
with other people.

The supported configuration options are currently the following:

## implicit_slide_ends

This option removes the need to use `<!-- end_slide -->` in between slides and instead assumes that if you use a slide 
title, then you're implying that the previous slide ended. For example, the following presentation:

```markdown
---
options:
  implicit_slide_ends: true
---

Tasty vegetables
================

* Potato

Awful vegetables
================

* Lettuce
```

Is equivalent to this "vanilla" one that doesn't use implicit slide ends.

```markdown
Tasty vegetables
================

* Potato

<!-- end_slide -->

Awful vegetables
================

* Lettuce
```

## end_slide_shorthand

This option allows using thematic breaks (`---`) as a delimiter between slides. When enabling this option, you can still 
use `<!-- end_slide -->` but any thematic break will also be considered a slide terminator.

```
---
options:
  end_slide_shorthand: true
---

this is a slide

---------------------

this is another slide
```

## h1_slide_titles

This options allows setting whether the first `h1` heading in a slide will automatically become the slide title:

```
---
options:
    h1_slide_titles: true
---

# title

# not the first, so no title
```

## command_prefix

Because _presenterm_ uses HTML comments to represent commands, it is necessary to make some assumptions on _what_ is a 
command and what isn't. The current heuristic is:

* If an HTML comment is laid out on a single line, it is assumed to be a command. This means if you want to use a real 
  HTML comment like `<!-- remember to say "potato" here -->`, this will raise an error.
* If an HTML comment is multi-line, then it is assumed to be a comment and it can have anything inside it. This means 
  you can't have a multi-line comment that contains a command like `pause` inside.

Depending on how you use HTML comments personally, this may be limiting to you: you cannot use any single line comments 
that are not commands. To get around this, the `command_prefix` option lets you configure a prefix that must be set in 
all commands for them to be configured as such. Any single line comment that doesn't start with this prefix will not be 
considered a command.

For example:

```
---
options:
  command_prefix: "cmd:"
---

<!-- remember to say "potato here" -->

Tasty vegetables
================

* Potato

<!-- cmd:pause -->

**That's it!**
```

In the example above, the first comment is ignored because it doesn't start with "cmd:" and the second one is processed 
because it does.

## incremental_lists

If you'd like all bullet points in all lists to show up with pauses in between you can enable the `incremental_lists` 
option:

```
---
options:
  incremental_lists: true
---

* pauses
* in
* between
```

Keep in mind if you only want specific bullet points to show up with pauses in between, you can use the 
[`incremental_lists` comment command](../features/commands.md#incremental-lists).

## strict_front_matter_parsing

This option tells _presenterm_ you don't care about extra parameters in presentation's front matter. This can be useful 
if you're trying to load a presentation made for another tool. The following presentation would only be successfully 
loaded if you set `strict_front_matter_parsing` to `false` in your configuration file:

```markdown
---
potato: 42
---

# Hi
```

## image_attributes_prefix

The [image size](../features/images.md#image-size) prefix (by default `image:`) can be configured to be anything you 
would want in case you don't like the default one. For example, if you'd like to set the image size by simply doing 
`![width:50%](path.png)` you would need to set:

```yaml
---
options:
  image_attributes_prefix: ""
---

![width:50%](path.png)
```

## auto_render_languages

This option allows indicating a list of languages for which the `+render` attribute can be omitted in their code 
snippets and will be implicitly considered to be set. This can be used for languages like `mermaid` so that graphs are 
always automatically rendered without the need to specify `+render` everywhere.

```yaml
---
options:
  auto_render_languages:
    - mermaid
---
```

## list_item_newlines

The option allows configuring the number of newlines in between list items, the default being `1`. This cam also be set 
via the `list_item_newlines` comment command.

```yaml
---
options:
    list_item_newlines: 2
---
```


================================================
FILE: docs/src/configuration/settings.md
================================================
# Settings

As opposed to options, the rest of these settings **can only be configured via the configuration file**.

## Default theme

The default theme can be configured only via the config file. When this is set, every presentation that doesn't set a 
theme explicitly will use this one:

```yaml
defaults:
  theme: light
```

You can also set a dark and light theme independently, _presenterm_ will detect terminal theme on launch by fetching
foreground and background color and pick the right theme:

```yaml
defaults:
  theme:
    light: light
    dark: dark
```

## Terminal font size

This is a parameter that lets you explicitly set the terminal font size in use. This should not be used unless you are 
in Windows, given there's no (easy) way to get the terminal window size so we use this to figure out how large the 
window is and resize images properly. Some terminals on other platforms may also have this issue, but that should not be 
as common.

If you are on Windows or you notice images show up larger/smaller than they should, you can adjust this setting in your 
config file:

```yaml
defaults:
  terminal_font_size: 16
```

## Preferred image protocol

By default _presenterm_ will try to detect which image protocol to use based on the terminal you are using. In case 
detection for some reason fails in your setup or you'd like to force a different protocol to be used, you can explicitly 
set this via the `--image-protocol` parameter or the configuration key `defaults.image_protocol`:

```yaml
defaults:
  image_protocol: kitty-local
```

Possible values are:
* `auto`: try to detect it automatically (default).
* `kitty-local`: use the kitty protocol in "local" mode, meaning both _presenterm_ and the terminal run in the same host 
  and can share the filesystem to communicate.
* `kitty-remote`: use the kitty protocol in "remote" mode, meaning _presenterm_ and the terminal run in different hosts 
  and therefore can only communicate via terminal escape codes.
* `iterm2`: use the iterm2 protocol.
* `sixel`: use the sixel protocol.

## Maximum presentation width

The `max_columns` property can be set to specify the maximum number of columns that the presentation will stretch to. If 
your terminal is larger than that, the presentation will stick to that size and will be centered, preventing it from 
looking too stretched.

```yaml
defaults:
  max_columns: 100
```

If you would like your presentation to be left or right aligned instead of centered when the terminal is too wide, you 
can use the `max_columns_alignment` key:

```yaml
defaults:
  max_columns: 100
  # Valid values: left, center, right
  max_columns_alignment: left
```

## Maximum presentation height

The `max_rows` and `max_rows_alignment` properties are analogous to `max_columns*` to allow capping the maximum number 
of rows:

```yaml
defaults:
  max_rows: 100
  # Valid values: top, center, bottom
  max_rows_alignment: left
```

## Incremental lists behavior

By default, [incremental lists](../features/commands.md) will pause before and after a list. If you would like to change 
this behavior, use the `defaults.incremental_lists` key:

```yaml
defaults:
  incremental_lists:
    # The defaults, change to false if desired.
    pause_before: true
    pause_after: true
```

## Validate terminal overflows

The `validate_overflows` property allows configuring whether _presenterm_ should make sure your presentation fits in the 
current terminal screen. This allows knowing whether any lines are too long to fit in the screen without having to 
scroll through every slide and manually check for that.

When the presentation is first loaded, after the presentation file is modified (if in development mode), and when you 
resize your terminal, _presenterm_ will make sure every slide in it fits. If any of them don't, an error will be 
displayed and you will need to resize your terminal until the error goes away or you exit the program.

This parameter supports multiple options:

* `never`: the default, where overflows aren't validated at all.
* `always`: overflow validation will always happen when running _presenterm_.
* `when_presenting`: only perform validation when in present mode. That is, when you're running `presenterm -p`.
* `when_developing`: only perform validation when running in development mode. That is, any time you're not using 
`presenterm -p`.

```yaml
defaults:
  validate_overflows: always
```

# Slide transitions

Slide transitions allow animating your presentation every time you move from a slide to the next/previous one. The 
configuration for slide transitions is the following:

```yaml
transition:
  # how long the transition should last.
  duration_millis: 750

  # how many frames should be rendered during the transition
  frames: 45

  # the animation to use
  animation:
    style: <style_name>
```

See the [slide transitions page](../features/slide-transitions.md) for more information on which animation styles are 
supported.

# Key bindings

Key bindings that _presenterm_ uses can be manually configured in the config file via the `bindings` key. The following 
is the default configuration:

```yaml
bindings:
  # the keys that cause the presentation to move forwards.
  next: ["l", "j", "<right>", "<page_down>", "<down>", " "]

  # the keys that cause the presentation to move backwards.
  previous: ["h", "k", "<left>", "<page_up>", "<up>"]

  # the keys that cause the presentation to move "fast" to the next slide. this will ignore:
  #
  # * Pauses.
  # * Dynamic code highlights.
  # * Slide transitions, if enabled.
  next_fast: ["n"]

  # same as `next_fast` but jumps fast to the previous slide.
  previous_fast: ["p"]

  # the key binding to jump to the first slide.
  first_slide: ["gg"]

  # the key binding to jump to the last slide.
  last_slide: ["G"]

  # the key binding to jump to a specific slide.
  go_to_slide: ["<number>G"]

  # the key binding to execute a piece of shell code.
  execute_code: ["<c-e>"]

  # the key binding to reload the presentation.
  reload: ["<c-r>"]

  # the key binding to toggle the slide index modal.
  toggle_slide_index: ["<c-p>"] 

  # the key binding to toggle the key bindings modal.
  toggle_bindings: ["?"] 

  # the key binding to close the currently open modal.
  close_modal: ["<esc>"]

  # the key binding to close the application.
  exit: ["<c-c>", "q"]

  # the key binding to suspend the application.
  suspend: ["<c-z>"]
```

You can choose to override any of them. Keep in mind these are overrides so if for example you change `next`, the 
default won't apply anymore and only what you've defined will be used.

# Snippet configurations

The configurations that affect code snippets in presentations.

## Snippet execution

[Snippet execution](../features/code/execution.md#executing-code-blocks) is disabled by default for security reasons. 
Besides passing in the `-x` command line parameter every time you run _presenterm_, you can also configure this globally 
for all presentations by setting:

```yaml
snippet:
  exec:
    enable: true
```

**Use this at your own risk**, especially if you're running someone else's presentations!

## Snippet execution + replace

[Snippet execution + replace](../features/code/execution.md#executing-and-replacing) is disabled by default for security 
reasons. Similar to `+exec`, this can be enabled by passing in the `-X` command line parameter or configuring it 
globally by setting:

```yaml
snippet:
  exec_replace:
    enable: true
```

**Use this at your own risk**. This will cause _presenterm_ to execute code without user intervention so don't blindly 
enable this and open a presentation unless you trust its origin!

## Custom snippet executors

If _presenterm_ doesn't support executing code snippets for your language of choice, please [create an 
issue](https://github.com/mfontanini/presenterm/issues/new)! Alternatively, you can configure this locally yourself by 
setting:

```yaml
snippet:
  exec:
    custom:
      # The keys should be the language identifier you'd use in a code block.
      c++:
        # The name of the file that will be created with your snippet's contents.
        filename: "snippet.cpp"

        # A list of environment variables that should be set before building/running your code.
        environment:
          MY_FAVORITE_ENVIRONMENT_VAR: foo

        # A prefix that indicates a line that starts with it should not be visible but should be executed if the
        # snippet is marked with `+exec`.
        hidden_line_prefix: "/// "

        # A list of commands that will be ran one by one in the same directory as the snippet is in.
        commands:
          # Compile if first
          - ["g++", "-std=c++20", "snippet.cpp", "-o", "snippet"]
          # Now run it 
          - ["./snippet"]
```

The output of all commands will be included in the code snippet execution output so if a command (like the `g++` 
invocation) was to emit any output, make sure to use whatever flags are needed to mute its output.

Also note that you can override built-in executors in case you want to run them differently (e.g. use `c++23` in the 
example above).

See more examples in the [executors.yaml](https://github.com/mfontanini/presenterm/blob/master/executors.yaml) file 
which defines all of the built-in executors. 

## Snippet rendering threads

Because some `+render` code blocks can take some time to be rendered into an image, especially if you're using 
[mermaid](https://mermaid.js.org/) charts, this is run asychronously. The number of threads used to render these, which 
defaults to 2, can be configured by setting:

```yaml
snippet:
  render:
    threads: 2
```

## Mermaid

The following configuration parameters can be set to alter the behavior when displaying 
[mermaid](https://mermaid.js.org/) diagrams.

### Config file

A custom [mermaid config file](https://mermaid.ai/open-source/config/schema-docs/config.html) can be configured via the 
`mermaid.config_file` config parameter. This should point to a configuration file where you can set any configs you 
consider appropriate, such as the font family to use:

```yaml
mermaid:
  config_file: /home/foo/my_config_file.yml
```

### Puppeteer config file

A custom puppeteer config file can be configured via the `mermaid.puppeteer_config_file` config parameter. This should 
point to a configuration file that will be given to puppeteer by the `mmdc` tool:

```yaml
mermaid:
  puppeteer_config_file: /home/foo/puppeteer.json
```

### Scaling

mermaid graphs will use a default scaling of `2` when invoking the mermaid CLI. If you'd like to change this use:


```yaml
mermaid:
  scale: 2
```

## D2 scaling

[d2](https://d2lang.com/) graphs will use the default scaling when invoking the d2 CLI. If you'd like to change this 
use:


```yaml
d2:
  scale: 2
```

## Enabling speaker note publishing

If you don't want to run _presenterm_ with `--publish-speaker-notes` every time you want to publish speaker notes, you 
can set the `speaker_notes.always_publish` attribute to `true`.

```yaml
speaker_notes:
  always_publish: true
```

# Presentation exports

The configurations that affect PDF and HTML exports.

## Export size

By default, the size of each page in the generated PDF and HTML files will depend on the size of your terminal. 

If you would like to instead configure the dimensions by hand, set the `export.dimensions` key:

```yaml
export:
  dimensions:
    columns: 80
    rows: 30
```

## Pause behavior

By default pauses will be ignored in generated PDF files. If instead you'd like every pause to generate a new page in 
the export, set the `export.pauses` attribute:

```yaml
export:
  pauses: new_slide
```

## Sequential snippet execution

When generating exports, snippets are executed in parallel to make the process faster. If your snippets require being 
executed sequentially, you can use the `export.snippets` parameter:

```yaml
export:
  snippets: sequential
```

## PDF font 

The PDF export can be configured to use a specific font installed in your system. Use the following keys to do so:

```yaml
export:
  pdf:
    fonts:
      normal: /usr/share/fonts/truetype/tlwg/TlwgMono.ttf
      italic: /usr/share/fonts/truetype/tlwg/TlwgMono-Oblique.ttf
      bold: /usr/share/fonts/truetype/tlwg/TlwgMono-Bold.ttf
      bold_italic: /usr/share/fonts/truetype/tlwg/TlwgMono-BoldOblique.ttf
```



================================================
FILE: docs/src/features/code/d2.md
================================================
# D2

[D2](https://d2lang.com/) snippets can be converted into images automatically for any snippets tagged with the `d2` 
language and using a `+render` attribute:

~~~markdown
```d2 +render
my_table: {
  shape: sql_table
  id: int {constraint: primary_key}
  last_updated: timestamp with time zone
}
```
~~~


**This requires having [d2](https://github.com/terrastruct/d2) installed**.

Similar to [mermaid diagrams support](mermaid.md), d2 diagrams:

* Will take some time because of how slow the d2 tool is.
* Can be scaled by using a `+width:<number>%` attribute in the snippet or by setting the `d2.scale` property in the 
config file, which is passed along to the `--scale` parameter to the d2 CLI.

## Theme

The theme of the rendered d2 diagrams can be changed through the `d2.theme` [theme](../themes/introduction.md) 
parameter. See the available themes in the [d2 docs](https://d2lang.com/tour/themes/).


================================================
FILE: docs/src/features/code/execution.md
================================================
# Snippet execution

## Executing code blocks

Annotating a code block with a `+exec` attribute will make it executable. Pressing `control+e` when viewing a slide that 
contains an executable block, the code in the snippet will be executed and the output of the execution will be displayed 
on a box below it. The code execution is stateful so if you switch to another slide and then go back, you will still see 
the output.

~~~markdown
```bash +exec
echo hello world
```
~~~

Code execution **must be explicitly enabled** by using either:

* The `-x` command line parameter when running _presenterm_.
* Setting the `snippet.exec.enable` property to `true` in your [_presenterm_ config 
file](../../configuration/settings.md#snippet-execution).

Refer to [the table in the highlighting page](highlighting.md#code-highlighting) for the list of languages for which 
code execution is supported.

---

[![asciicast](https://asciinema.org/a/BbAY817esxagCgPtnKUwgYnHr.svg)](https://asciinema.org/a/BbAY817esxagCgPtnKUwgYnHr)

> [!warning]
> Run code in presentations at your own risk! Especially if you're running someone else's presentation. Don't blindly 
> enable snippet execution!

### Output placing

By default a snippet's output will always show up right below the snippet. However, if you wanted to show the output in 
a different place in a slide (e.g. another column) or even in another slide you can do this by:

1. Defining a snippet's identifier:

~~~markdown
```bash +exec +id:foo
echo hellow world
```
~~~

2. Referencing that identifier where you want the output to appear by using the `snippet_output` comment command:

~~~markdown
<!-- snippet_output: foo -->
~~~

A single snippet can be referenced multiple times in multiple slides, as long as the slide you're referencing it in 
comes after the snippet. The snippet will only be executed once, and every `snippet_output` command will display that 
single execution's output.

### Validating snippets

While you're developing your presentation you probably want to make sure the executable snippets you write in it are 
correct and don't contain any syntax errors. While you can do this by constantly pressing `<c-e>` every time you change 
a snippet, this is automatically done by _presenterm_ if you pass in the `--validate-snippets` flag.

When you pass in this flag, _presenterm_ will:

* Automatically run all `+exec`, `+exec_replace`, and `+validate` snippets as soon as your presentation starts. Note 
that the `+validate` flag is a special one that doesn't make a snippet executable but still validates it by running it 
during development.
* Report an error if any of the snippets returns an exit code other than 0.
* Re-run all snippets `+exec` and `+exec_replace` snippets every time the presentation is reloaded.

In case you expect a snippet to return an exit code other than 0, you can use the `+expect:failure` flag. This will 
cause _presenterm_ to display an error if the snippet does not fail.

For example, the following defines a snippet that's not executable but that will be validated if `--validate-snippets` 
is passed in and will display an error if the snippet does not fail.

```rust +validate +expect:failure
fn main() {
    let q = 42;
    let w = q + "foo"; // oops
}
```

## Running code in pseudo terminal (PTY)

By using the `+pty` attribute, you can run a code snippet inside a pseudo terminal. This allows running tools like `top` 
and `htop` which move the cursor around, clear the screen, etc, and have them behave how you'd expect.

[![asciicast](https://asciinema.org/a/PWdPtehxI6xwM7Yt.svg)](https://asciinema.org/a/PWdPtehxI6xwM7Yt)

Note that this can be used with snippets in any language, not necessarily only shell scripts. 

> [!note]
> Support for sending keyboard input into running scripts is planned but not currently supported.

### Specifying PTY size

The size of the PTY used to execute the code will be expanded to fit the screen. A custom size can be set by using the 
`+pty:<columns>:<rows>` syntax, e.g. `+pty:80:30`.

### Standby mode

A `+pty:standby` block indicates the area of the slide the PTY will be rendered on should always be visible, even before 
the code is executed. Note that if you're also configuring the PTY size, the syntax is `+pty:standby:<columns>:<rows>` 

[![asciicast](https://asciinema.org/a/IrclITxMSkBZPPH3.svg)](https://asciinema.org/a/IrclITxMSkBZPPH3)

## Executing and replacing

Similar to `+exec`, `+exec_replace` causes a snippet to be executable but:

* Execution happens automatically without user intervention.
* The snippet will be automatically replaced with its execution output.

This can be useful to run programs that generate some form of ASCII art that you'd like to generate dynamically.

[![asciicast](https://asciinema.org/a/hklQARZKb5sP5mavL4cGgbYXD.svg)](https://asciinema.org/a/hklQARZKb5sP5mavL4cGgbYXD)

Because of the risk involved in `+exec_replace`, where code gets automatically executed when running a presentation, 
this requires users to explicitly opt in to it. This can be done by either passing in the `-X` command line parameter
or setting the `snippet.exec_replace.enable` flag in your configuration file to `true`.

## Automatic execution

The `+auto_exec` property behaves like a `+exec` code block but doesn't require pressing `<c-e>` to execute it.

## Alternative executors

Some languages support alternative executors. For example, `rust` code can be ran via 
[`rust-script`](https://rust-script.org/), which allows you to use external crates. These executors can be used by 
specifying `:<executor-name>` after `+exec` or `+exec_replace`.

For example, the following `rust` snippet will be executed using `rust-script`:

~~~markdown
```rust +exec:rust-script
# //! ```cargo
# //! [dependencies]
# //! time = "0.1.25"
# //! ```
# // The lines above will be hidden
fn main() {
    println!("the time is {}", time::now().rfc822z());
}
```
~~~

The supported alternative executors are:

* `rust-script` for `rust` snippets.
* `pytest` and `uv` for `python` snippets.

## Code to image conversions

The `+image` attribute behaves like `+exec_replace` but also assumes the output of the executed snippet will be an 
image, and it will render it as such. For this to work, the code **must only emit an image in jpg/png formats** and 
nothing else.

For example, this would render the demo presentation's image:

~~~markdown
```bash +image
cat examples/doge.png
```
~~~

This attribute carries the same risks as `+exec_replace` and therefore needs to be enabled via the same flags.

## Executing snippets that need a TTY

If you're trying to execute a program like `top` that needs to run on a TTY as it renders text, clears the screen, etc, 
you can use the `+acquire_terminal` modifier on a code already marked as executable with `+exec`. Executing snippets 
tagged with these two attributes will cause _presenterm_ to suspend execution, the snippet will be invoked giving it the 
raw terminal to do whatever it needs, and upon its completion _presenterm_ will resume its execution.

[![asciicast](https://asciinema.org/a/AHfuJorCNRR8ZEnfwQSDR5vPT.svg)](https://asciinema.org/a/AHfuJorCNRR8ZEnfwQSDR5vPT)

## Styled execution output

Snippets that generate output which contains escape codes that change the colors or styling of the text will be parsed 
and displayed respecting those styles. Do note that you may need to force certain tools to use colored output as they 
will likely not use it by default.

For example, to get colored output when invoking `ls` you can use:

~~~markdown
```bash +exec
ls /tmp --color=always
```
~~~

The parameter or way to enable this will depend on the tool being invoked.

## Hiding code lines

When you mark a code snippet as executable via the `+exec` flag, you may not be interested in showing _all the lines_ to 
your audience, as some of them may not be necessary to convey your point. For example, you may want to hide imports, 
non-essential functions, initialization of certain variables, etc. For this purpose, _presenterm_ supports a prefix 
under certain programming languages that let you indicate a line should be executed when running the code but should not 
be displayed in the presentation.

For example, in the following code snippet only the print statement will be displayed but the entire snippet will be 
ran:

~~~markdown
```rust
# fn main() {
println!("Hello world!");
# }
```
~~~

Rather than blindly relying on a prefix that may have a meaning in a language, prefixes are chosen on a per language 
basis. The languages that are supported and their prefix is:

* rust: `# `.
* python/bash/fish/shell/zsh/kotlin/java/javascript/typescript/c/c++/go: `/// `.

This means that any line in a rust code snippet that starts with `# ` will be hidden, whereas all lines in, say, a 
golang code snippet that starts with a `/// ` will be hidden.

## Pre-rendering 

Some languages support pre-rendering. This means the code block is transformed into something else when the presentation 
is loaded. The languages that currently support this are _mermaid_, _LaTeX_, and _typst_ where the contents of the code 
block is transformed into an image, allowing you to define formulas as text in your presentation. This can be done by 
using the `+render` attribute on a code block.

See the [LaTeX and typst](latex.md), [mermaid](mermaid.md), and [d2](d2.md) docs for more information.



================================================
FILE: docs/src/features/code/highlighting.md
================================================
# Code highlighting

Code highlighting is supported for the following languages:

| Language   | Execution support |
|------------|-------------------|
| ada        |                   |
| asp        |                   |
| awk        |                   |
| bash       |         ✓         |
| batchfile  |                   |
| C          |         ✓         |
| cmake      |                   |
| crontab    |                   |
| C#         |         ✓         |
| clojure    |                   |
| C++        |         ✓         |
| CSS        |                   |
| D          |                   |
| diff       |                   |
| docker     |                   |
| dotenv     |                   |
| elixir     |                   |
| elm        |                   |
| erlang     |                   |
| fish       |         ✓         |
| F#         |         ✓         |
| go         |         ✓         |
| haskell    |         ✓         |
| HTML       |                   |
| java       |         ✓         |
| javascript |         ✓         |
| json       |                   |
| julia      |         ✓         |
| kotlin     |         ✓         |
| latex      |                   |
| lua        |         ✓         |
| makefile   |                   |
| markdown   |                   |
| nix        |                   |
| ocaml      |                   |
| perl       |         ✓         |
| php        |         ✓         |
| protobuf   |                   |
| puppet     |                   |
| python     |         ✓         |
| R          |         ✓         |
| ruby       |         ✓         |
| rust       |         ✓         |
| scala      |                   |
| shell      |         ✓         |
| sql        |                   |
| swift      |                   |
| svelte     |                   |
| tcl        |                   |
| toml       |                   |
| terraform  |                   |
| typescript |                   |
| xml        |                   |
| yaml       |                   |
| vue        |                   |
| zig        |                   |
| zsh        |         ✓         |

Other languages that are supported are:

* nushell, for which highlighting isn't supported but execution is.

If there's a language that is not in this list and you would like it to be supported, please [create an 
issue](https://github.com/mfontanini/presenterm/issues/new). If you'd also like code execution support, provide details 
on how to compile (if necessary) and run snippets for that language. You can also configure how to run code snippet for 
a language locally in your [config file](../../configuration/settings.md#custom-snippet-executors).

## Enabling line numbers

If you would like line numbers to be shown on the left of a code block use the `+line_numbers` switch after specifying
the language in a code block:

~~~markdown
```rust +line_numbers
   fn hello_world() {
       println!("Hello world");
   }
```
~~~

## Selective highlighting

By default, the entire code block will be syntax-highlighted. If instead you only wanted a subset of it to be
highlighted, you can use braces and a list of either individual lines, or line ranges that you'd want to highlight.

~~~markdown
```rust {1,3,5-7}
   fn potato() -> u32 {         // 1: highlighted
                                // 2: not highlighted
       println!("Hello world"); // 3: highlighted
       let mut q = 42;          // 4: not highlighted
       q = q * 1337;            // 5: highlighted
       q                        // 6: highlighted
   }                            // 7: highlighted
```
~~~

## Dynamic highlighting

Similar to the syntax used for selective highlighting, dynamic highlighting will change which lines of the code in a
code block are highlighted every time you move to the next/previous slide.

This is achieved by using the separator `|` to indicate what sections of the code will be highlighted at a given time.
You can also use `all` to highlight all lines for a particular frame.

~~~markdown
```rust {1,3|5-7}
   fn potato() -> u32 {

       println!("Hello world");
       let mut q = 42;
       q = q * 1337;
       q
   }
```
~~~

In this example, lines 1 and 3 will be highlighted initially. Then once you press a key to move to the next slide, lines
1 and 3 will no longer be highlighted and instead lines 5 through 7 will. This allows you to create more dynamic
presentations where you can display sections of the code to explain something specific about each of them.

See this real example of how this looks like.

[![asciicast](https://asciinema.org/a/iCf4f6how1Ux3H8GNzksFUczI.svg)](https://asciinema.org/a/iCf4f6how1Ux3H8GNzksFUczI)

## Including external code snippets

The `file` snippet type can be used to specify an external code snippet that will be included and highlighted as usual. 

~~~markdown
```file +exec +line_numbers
path: snippet.rs
language: rust
```
~~~

If you'd like to include only a subset of the file, you can use the optional fields `start_line` and `end_line`:

~~~markdown
```file +exec +line_numbers
path: snippet.rs
language: rust
# Only show lines 5-10
start_line: 5
end_line: 10
```
~~~

## Showing a snippet without a background

Using the `+no_background` flag will cause the snippet to have no background. This is useful when combining it with the 
`+exec_replace` flag described further down.

## Adding highlighting syntaxes for new languages

_presenterm_ uses the syntaxes supported by [bat](https://github.com/sharkdp/bat) to highlight code snippets, so any 
languages supported by _bat_ natively can be added to _presenterm_ easily. Please create a ticket or use 
[this](https://github.com/mfontanini/presenterm/pull/385) as a reference to submit a pull request to make a syntax 
officially supported by _presenterm_ as well.

If a language isn't natively supported by _bat_ but you'd like to use it, you can follow
[this guide in the bat docs](https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions) and
invoke _bat_ directly in a presentation:

~~~markdown
```bash +exec_replace
bat --color always script.py
```
~~~

> [!note]
> Check the [code execution docs](execution.md#executing-and-replacing) for more details on how to allow the tool to run 
> `exec_replace` blocks.


================================================
FILE: docs/src/features/code/latex.md
================================================
# LaTeX and typst

`latex` and `typst` code blocks can be marked with the `+render` attribute (see [highlighting](highlighting.md)) to have 
them rendered into images when the presentation is loaded. This allows you to define formulas in text rather than having 
to define them somewhere else, transform them into an image, and them embed it.

For example, the following presentation:

~~~
# Formulas

```latex +render
\[ \sum_{n=1}^{\infty} 2^{-n} = 1 \]
```
~~~

Would be rendered like this:

![](../../assets/formula.png)

## Dependencies

### typst

The engine used to render both of these languages is [typst](https://github.com/typst/typst). _typst_ is easy to 
install, lightweight, and boilerplate free as compared to _LaTeX_.

### pandoc

For _LaTeX_ code rendering both _typst_ and [pandoc](https://github.com/jgm/pandoc) are required. How this works is the 
_LaTeX_ code you write gets transformed into _typst_ code via _pandoc_ and then rendered by using _typst_. This lets us:

* Have the same look/feel on generated formulas for both languages.
* Avoid having to write lots of boilerplate _LaTeX_ to make rendering for that language work.
* Have the same logic to render formulas for both languages, except with a small preparation step for _LaTeX_.

## Controlling PPI

_presenterm_ lets you define how many Pixels Per Inch (PPI) you want in the generated images. This is important because 
as opposed to images that you manually include in your presentation, where you control the exact dimensions, the images 
generated on the fly will have a fixed size. Configuring the PPI used during the conversion can let you adjust this: the 
higher the PPI, the larger the generated images will be.

Because as opposed to most configurations this is a very environment-specific config, the PPI parameter is not part of 
the theme definition but is instead has to be set in _presenterm_'s [config file](../../configuration/introduction.md):

```yaml
typst:
  ppi: 400
```

The default is 300 so adjust it and see what works for you.

## Image paths

If you're including an image inside a _typst_ snippet, you must:

* Use absolute paths, e.g. `#image("/image1.png")`.
* Place the image in the same or a sub path of the path where the presentation is. That is, if your presentation file is 
at `/tmp/foo/presentation.md`, you can place images in `/tmp/foo`, and `/tmp/foo/bar` but not under `/tmp/bar`. This is 
because of the absolute path rule above: the path will be considered to be relative to the presentation file's 
directory.

## Controlling the image size

You can also set the generated image's size on a per code snippet basis by using the `+width` modifier which specifies 
the width of the image as a percentage of the terminal size.

~~~markdown
```typst +render +width:50%
$f(x) = x + 1$
```
~~~

## Customizations

The colors and margin of the generated images can be defined in your theme:

```yaml
typst:
  colors:
    background: ff0000
    foreground: 00ff00

  # In points
  horizontal_margin: 2
  vertical_margin: 2
```


================================================
FILE: docs/src/features/code/mermaid.md
================================================
## Mermaid

[mermaid](https://mermaid.js.org/) snippets can be converted into images automatically in any code snippet tagged with 
the `mermaid` language and a `+render` tag:

~~~markdown
```mermaid +render
sequenceDiagram
    Mark --> Bob: Hello!
    Bob --> Mark: Oh, hi mark!
```
~~~

**This requires having [mermaid-cli](https://github.com/mermaid-js/mermaid-cli) installed**.

Note that because the mermaid CLI will spin up a browser under the hood, this may not work in all environments and can 
also be a bit slow (e.g. ~2 seconds to generate every image). Mermaid graphs are rendered asynchronously by a number of 
threads that can be configured in the [configuration file](../../configuration/settings.md#snippet-rendering-threads). 
This configuration value currently defaults to 2.

The size of the rendered image can be configured by changing:
* The `mermaid.scale` [configuration parameter](../../configuration/settings.md#mermaid-scaling).
* Using the `+width:<number>%` attribute in the code snippet.

For example, this diagram will take up 50% of the width of the window and will preserve its aspect ratio:

~~~markdown
```mermaid +render +width:50%
sequenceDiagram
    Mark --> Bob: Hello!
    Bob --> Mark: Oh, hi mark!
```
~~~

It is recommended to change the `mermaid.scale` parameter until images look big enough and then adjust on an image by 
image case if necessary using the `+width` attribute. Otherwise, using a small scale and then scaling via `+width` may 
cause the image to become blurry.

## Theme

The theme of the rendered mermaid diagrams can be changed through the following [theme](../themes/introduction.md) 
parameters:

* `mermaid.background` the background color passed to the CLI (e.g., `transparent`, `red`, `#F0F0F0`).
* `mermaid.theme` the [mermaid theme](https://mermaid.js.org/config/theming.html#available-themes) to use.

## Always render diagrams

If you don't want to use `+render` every time, you can configure which languages get this automatically via the [config 
file](../../configuration/settings.md#auto_render_languages).


================================================
FILE: docs/src/features/commands.md
================================================
# Comment commands

_presenterm_ uses "comment commands" in the form of HTML comments to let the user specify certain behaviors that can't 
be specified by vanilla markdown.

## Pauses

Pauses allow the sections of the content in your slide to only show up when you advance in your presentation. That is, 
only after you press, say, the right arrow will a section of the slide show up. This can be done by the `pause` comment 
command:

```html
<!-- pause -->
```

## Font size

The font size can be changed by using the `font_size` command:

```html
<!-- font_size: 2 -->
```

This causes the remainder of the slide to use the font size specified. The font size can range from 1 to 7, 1 being the 
default.

> [!note]
> This is currently only supported in the [_kitty_](https://sw.kovidgoyal.net/kitty/) terminal and only as of version 
> 0.40.0. See the notes on font sizes on the [introduction page](introduction.md#font-sizes) for more information on 
> this.

## Jumping to the vertical center

The command `jump_to_middle` lets you jump to the middle of the page vertically. This is useful in combination
with slide titles to create separator slides:

```markdown
blablabla

<!-- end_slide -->

<!-- jump_to_middle -->

Farming potatoes
===

<!-- end_slide -->
```

This will create a slide with the text "Farming potatoes" in the center, rendered using the slide title style.

## Explicit new lines

The `newline`/`new_line` and `newlines`/`new_lines` commands allow you to explicitly create new lines. Because markdown 
ignores multiple line breaks in a row, this is useful to create some spacing where necessary:

```markdown
hi

<!-- new_lines: 10 -->

mom

<!-- new_line -->

bye
```

## Incremental lists

Using `<!-- pause -->` in between each bullet point a list is a bit tedious so instead you can use the 
`incremental_lists` command to tell _presenterm_ that **until the end of the current slide** you want each individual 
bullet point to appear only after you move to the next slide:

```markdown
<!-- incremental_lists: true -->

* this
* appears
* one after
* the other

<!-- incremental_lists: false -->

* this appears
* all at once
```

## Number of lines in between list items

The `list_item_newlines` option lets you configure the number of new lines in between list items in the remainder of a 
slide. This can be helpful to "unpack" a list that only has a few entries and you want it to take up more space in a 
slide. This can also be configured for all lists via the [`options.list_item_newlines` 
option](../configuration/options.md#list_item_newlines).

```markdown
<!-- list_item_newlines: 2 -->

* this
* is
* more
* spaced
```

## Including external markdown files

By using the `include` command you can include the contents of an external markdown file as if it was part of the 
original presentation file:

```markdown
<!-- include: foo.md -->
```

Any files referenced by an included file will have their paths relative to that path. e.g. if you include `foo/bar.md` 
and that file contains an image `tar.png`, that image will be looked up in `foo/tar.png`.

## No footer

If you don't want the footer to show up in some particular slide for some reason, you can use the `no_footer` command:

```html
<!-- no_footer -->
```

## Skip slide

If you don't want a specific slide to be included in the presentation use the `skip_slide` command:

```html
<!-- skip_slide -->
```

## Text alignment

The text alignment for the remainder of the slide can be configured via the `alignment` command, which can use values: 
`left`, `center`, and `right`:

```markdown
<!-- alignment: left -->

left alignment, the default

<!-- alignment: center -->

centered

<!-- alignment: right -->

right aligned
```


## User comments

User comments such as personal notes, TODOs, and other documentation that will
be ignored during presentation rendering can be added using these formats:

```markdown
<!-- // This is a user comment -->
<!-- comment: This is also a user comment which won't be rendered -->
```

These are useful for:

- Personal notes and reminders.
- TODO items and planning notes.
- Source references and attribution.

## Listing available comment commands

The `--list-comment-commands` CLI option outputs all available comment commands to stdout, making it easy to discover and use them in external tools and editors.

### Purpose

This feature is designed to:
- Provide a machine-readable list of all comment commands
- Enable editor integrations for autocompletion and snippets
- Allow validation of comment commands in external tools
- Serve as a quick reference without consulting documentation

### Usage

```bash
# List all available comment commands
presenterm --list-comment-commands

# Use with fzf for interactive selection
presenterm --list-comment-commands | fzf

# Pipe to grep to filter specific commands
presenterm --list-comment-commands | grep alignment
```

### Output format

Each command is output on a separate line with appropriate default values where applicable:

```
<!-- pause -->
<!-- end_slide -->
<!-- new_line -->
<!-- new_lines: 2 -->
<!-- jump_to_middle -->
<!-- column_layout: [1, 2] -->
<!-- column: 0 -->
<!-- reset_layout -->
<!-- incremental_lists: true -->
<!-- incremental_lists: false -->
<!-- no_footer -->
<!-- font_size: 2 -->
<!-- alignment: left -->
<!-- alignment: center -->
<!-- alignment: right -->
<!-- skip_slide -->
<!-- list_item_newlines: 2 -->
<!-- include: file.md -->
<!-- speaker_note: Your note here -->
<!-- snippet_output: identifier -->
```

### Editor integration example: Vim

For Vim users with fzf.vim installed, you can add this to your `.vimrc` to enable quick insertion of comment commands:

```vim
" Presenterm comment command helper
if executable('presenterm') && executable('fzf')
  inoremap <expr> <c-k> fzf#vim#complete(fzf#wrap({
        \ 'source':  'presenterm --list-comment-commands',
        \ 'options': '--header "Comment Command Selection" --no-hscroll',
        \ 'reducer': { lines -> lines[0] } }))
endif
```

With this configuration, pressing `Ctrl+K` in insert mode will open an fzf picker with all available comment commands, allowing you to quickly select and insert them into your presentation.


================================================
FILE: docs/src/features/exports.md
================================================
# Exporting presentations

Presentations can be exported to PDF and HTML, to allow easily sharing the slide deck at the end of a presentation.

## PDF

Presentations can be converted into PDF by using [weasyprint](https://pypi.org/project/weasyprint/). Follow their 
[installation instructions](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html) since it may require you 
to install extra dependencies for the tool to work.

> [!note]
> If you were using _presenterm-export_ before it was deprecated, that tool already required _weasyprint_ so it is 
> already installed in whatever virtual env you were using and there's nothing to be done.


After you've installed _weasyprint_, run _presenterm_ with the `--export-pdf` parameter to generate the output PDF:

```bash
presenterm --export-pdf examples/demo.md
```

The output PDF will be placed in `examples/demo.pdf`. Alternatively you can use the `--output` flag to specify where you 
want the output file to be written to.

> [!note]
> If you're using a separate virtual env to install _weasyprint_ just make sure you activate it before running 
> _presenterm_ with the `--export-pdf` parameter.

> [!note]
> If you have [uv](https://github.com/astral-sh/uv) installed you can simply run: 
> ```bash
> uv run --with weasyprint presenterm --export-pdf examples/demo.md
> ```

## HTML

Similarly, using the `--export-html` parameter allows generating a single self contained HTML file that contains all 
images and styles embedded in it. As opposed to PDF exports, this requires no extra dependencies:

```bash
presenterm --export-html examples/demo.md
```

The output file will be placed in `examples/demo.html` but this behavior can be configured via the `--output` flag just 
like for PDF exports.

# Configurable behavior

See the [settings page](../configuration/settings.md#presentation-exports) to see all the configurable behavior around 
presentation exports.



================================================
FILE: docs/src/features/images.md
================================================
# Images

Images are supported and will render in your terminal as long as it supports either the [iterm2 image 
protocol](https://iterm2.com/documentation-images.html), the [kitty graphics 
protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/), or [sixel](https://saitoha.github.io/libsixel/). Some of 
the terminals where at least one of these is supported are:

* [kitty](https://sw.kovidgoyal.net/kitty/)
* [iterm2](https://iterm2.com/)
* [WezTerm](https://wezfurlong.org/wezterm/index.html)
* [ghostty](https://ghostty.org/)
* [foot](https://codeberg.org/dnkl/foot)

---

Things you should know when using image tags in your presentation's markdown are:
* Image paths are relative to your presentation path. That is a tag like `![](food/potato.png)` will be looked up at 
  `$PRESENTATION_DIRECTORY/food/potato.png`.
* Images will be rendered by default in their original size. That is, if your terminal is 300x200px and your image is 
200x100px, it will take up 66% of your horizontal space and 50% of your vertical space.
* The exception to the point above is if the image does not fit in your terminal, it will be resized accordingly while 
  preserving the aspect ratio.
* If your terminal does not support any of the graphics protocol above, images will be rendered using ascii blocks. It 
  ain't great but it's something!
* Remote images are not supported [by design](https://github.com/mfontanini/presenterm/issues/213#issuecomment-1950342423).

## tmux

If you're using tmux, you will need to enable the [allow-passthrough 
option](https://github.com/tmux/tmux/wiki/FAQ#what-is-the-passthrough-escape-sequence-and-how-do-i-use-it) for images to 
work correctly.

## Image size

The size of each image can be set by using the `image:width` or `image:w` attributes in the image tag. For example, the 
following will cause the image to take up 50% of the terminal width:

```markdown
![image:width:50%](image.png)
```

The image will always be scaled to preserve its aspect ratio and it will not be allowed to overflow vertically nor 
horizontally.

## Protocol detection

By default the image protocol to be used will be automatically detected. In cases where this detection fails, you can 
set it manually via the `--image-protocol` parameter or by setting it in the [config 
file](../configuration/settings.md#preferred-image-protocol).


================================================
FILE: docs/src/features/introduction.md
================================================
# Introduction

This guide teaches you how to use _presenterm_. At this point you should have already installed _presenterm_, otherwise 
visit the [installation](../install.md) guide to get started.

## Quick start

Download the demo presentation and run it using:

```bash
git clone https://github.com/mfontanini/presenterm.git
cd presenterm
presenterm examples/demo.md
```

# Presentations

A presentation in _presenterm_ is a single markdown file. Every slide in the presentation file is delimited by a line 
that contains a single HTML comment:

```html
<!-- end_slide -->
```

Presentations can contain most commonly used markdown elements such as ordered and unordered lists, headings, formatted 
text (**bold**, _italics_, ~strikethrough~, `inline code`, etc), code blocks, block quotes, tables, etc.

## Introduction slide

By setting a front matter at the beginning of your presentation you can configure the title, sub title, author and other 
metadata about your presentation. Doing so will cause _presenterm_ to create an introduction slide:

```yaml
---
title: "My _first_ **presentation**"
sub_title: (in presenterm!)
author: Myself
---
```

All of these attributes are optional and should be avoided if an introduction slide is not needed. Note that the `title` 
key can contain arbitrary markdown so you can use bold, italics, `<span>` tags, etc.

### Multiple authors

If you're creating a presentation in which there's multiple authors, you can use the `authors` key instead of `author`
and list them all this way:

```yaml
---
title: Our first presentation
authors:
  - Me
  - You
---
```

## Slide titles

Any [setext header](https://spec.commonmark.org/0.30/#setext-headings) will be considered to be a slide title and will 
be rendered in a more slide-title-looking way. By default this means it will be centered, some vertical padding will be 
added and the text color will be different.

~~~markdown
Hello
===
~~~

> [!note]
> See the [themes](themes/introduction.md) section on how to customize the looks of slide titles and any other element 
> in a presentation.

## Ending slides

While other applications use a thematic break (`---`) to mark the end of a slide, _presenterm_ uses a special 
`end_slide` HTML comment:

```html
<!-- end_slide -->
```

This makes the end of a slide more explicit and easy to spot while you're editing your presentation. See the 
[configuration](../configuration/options.md#implicit_slide_ends) if you want to customize this behavior.

If you really would prefer to use thematic breaks (`---`) to delimit slides, you can do that by enabling the 
[`end_slide_shorthand`](../configuration/options.md#end_slide_shorthand) options.

## Colored text

`span` HTML tags can be used to provide foreground and/or background colors to text. There's currently two ways to 
specify colors:

* Via the `style` attribute, in which only the CSS attributes `color` and `background-color` can be used to set the 
foreground and background colors respectively. Colors used in both CSS attributes can refer to 
[theme palette colors](themes/definition.md#color-palette) by using the `palette:<name>` or `p:<name` syntaxes.
* Via the `class` attribute, which must point to a class defined in the [theme 
palette](themes/definition.md#color-palette). Classes allow configuring foreground/background color combinations to be 
used across your presentation.

For example, the following will use `ff0000` as the foreground color and whatever the active theme's palette defines as 
`foo`:

```markdown
<span style="color: #ff0000; background-color: palette:foo">colored text!</span>
```

Alternatively, can you can define a class that contains a foreground/background color combination in your theme's 
palette and use it:

```markdown
<span class="my_class">colored text!</span>
```

> [!note]
> Keep in mind **only `span` tags are supported**.

## Font sizes

The [_kitty_](https://sw.kovidgoyal.net/kitty/) terminal added in version 0.40.0 support for a new protocol that allows 
TUIs to specify the font size to be used when printing text. _presenterm_ is one of the first applications supports this 
protocol in various places:

* Themes can specify it in the presentation title in the introduction slide, in slide titles, and in headers by using 
the `font_size` property. All built in themes currently set font size to 2 (1 is the default) for these elements.
* Explicitly by using the `font_size` comment command:

```markdown
# Normal text

<!-- font_size: 2 -->

# Larger text
```

Terminal support for this feature is verified when _presenterm_ starts and any attempt to change the font size, be it 
via the theme or via the comment command, will be ignored if it's not supported.

# Key bindings

Navigation within a presentation should be intuitive: jumping to the next/previous slide can be done by using the arrow 
keys, _hjkl_, and page up/down keys.

Besides this:

* Jumping to the first slide: `gg`.
* Jumping to the last slide: `G`.
* Jumping to a specific slide: `<slide-number>G`.
* Exit the presentation: `<ctrl>c`.

You can check all the configured keybindings by pressing `?` while running _presenterm_.

## Configuring key bindings

If you don't like the default key bindings, you can override them in the [configuration 
file](../configuration/settings.md#key-bindings).

# Modals

_presenterm_ currently has 2 modals that can provide some information while running the application. Modals can be 
toggled using some key combination and can be hidden using the escape key by default, but these can be configured via 
the [configuration file key bindings](../configuration/settings.md#key-bindings).

## Slide index modal

This modal can be toggled by default using `control+p` and lets you see an index that contains a row for every slide in 
the presentation, including its title and slide index. This allows you to find a slide you're trying to jump to 
quicklier rather than scanning through each of them.

[![asciicast](https://asciinema.org/a/1VgRxVIEyLrMmq6OZ3oKx4PGi.svg)](https://asciinema.org/a/1VgRxVIEyLrMmq6OZ3oKx4PGi)

## Key bindings modal

The key bindings modal displays the key bindings for each of the supported actions and can be opened by pressing `?`.

## Toggle visual grid

Press uppercase `T` by default to toggle the layout grid. This is useful when using a column layout and trying to 
understand how wide each column is. See [this PR](https://github.com/mfontanini/presenterm/pull/718) for more details.

# Hot reload

Unless you run in presentation mode by passing in the `--present` parameter, _presenterm_ will automatically reload your 
presentation file every time you save it. _presenterm_ will also automatically detect which specific slide was modified 
and jump to it so you don't have to be jumping back and forth between the source markdown and the presentation to see 
how the changes look like.

[![asciicast](https://asciinema.org/a/bu9ITs8KhaQK5OdDWnPwUYKu3.svg)](https://asciinema.org/a/bu9ITs8KhaQK5OdDWnPwUYKu3)


================================================
FILE: docs/src/features/layout.md
================================================
# Layouts

_presenterm_ currently supports a column layout that lets you split parts of your slides into column. This allows you to 
put text on one side, and code/images on the other, or really organize markdown into columns in any way you want.

This is done by using commands, just like `pause` and `end_slide`, in the form of HTML comments. This section describes 
how to use those.

## Wait, why not HTML?

While markdown _can_ contain HTML tags (beyond comments!) and we _could_ represent this using divs with alignment, I 
don't really want to:

1. Deal with HTML and all the implications this would have. e.g. nesting many divs together and all the chaos that would 
   bring to the rendering code.
2. Require people to write HTML when we have such a narrow use-case for it here: we only want column layouts.

Because of this, _presenterm_ doesn't let you use HTML and instead has a custom way of specifying column layouts.

## Column layout

The way to specify column layouts is by first creating a layout, and then telling _presenterm_ you want to enter each of 
the column in it as you write your presentation.

### Defining layouts

Defining a layout is done via the `column_layout` command, in the form of an HTML comment:

```html
<!-- column_layout: [3, 2] -->
```

This defines a layout with 2 columns where:
* The total number of "size units" is `3 + 2 = 5`. You can think of this as the terminal screen being split into 5 
  pieces vertically.
* The first column takes 3 out of those 5 pieces/units, or in other words 60% of the terminal screen.
* The second column takes 2 out of those 5 pieces/units, or in other words 40% of the terminal screen.

You can use any number of columns and with as many units you want on each of them. This lets you decide how to structure
the presentation in a fairly straightforward way.

### Using columns

Once a layout is defined, you just need to specify that you want to enter a column before writing any text to it by 
using the `column` command:

```html
<!-- column: 0 -->
```

Now all the markdown you write will be placed on the first column until you either:

* Reset the layout by using the `reset_layout` command.
* The slide ends.
* You jump into another column by using the `column` command again.

## Example

The following example puts all of this together by defining 2 columns, one with some code and bullet points, another one 
with an image, and some extra text at the bottom that's not tied to any columns.

~~~markdown
Layout example
==============

<!-- column_layout: [2, 1] -->

<!-- column: 0 -->

This is some code I like:

```rust
fn potato() -> u32 {
    42
}
```

Things I like about it:
1. Potato
2. Rust
3. The image on the right

<!-- column: 1 -->

![](examples/doge.png)

_Picture by Alexis Bailey / CC BY-NC 4.0_

<!-- reset_layout -->

Because we just reset the layout, this text is now below both of the columns.
~~~

This would render the following way:

![](../assets/layouts.png)

## Other uses

Besides organizing your slides into columns, you can use column layouts to center a piece of your slide. For example, if 
you want a certain portion of your slide to be centered, you could define a column layout like `[1, 3, 1]` and then only 
write content into the middle column. This would make your content take up the center 60% of the screen.



================================================
FILE: docs/src/features/slide-transitions.md
================================================
# Slide transitions

Slide transitions allow animating your presentation every time you move from a slide to the next/previous one. See the 
[configuration page](../configuration/settings.md#slide-transitions) to learn how to configure transitions.

The following animations are supported:

## `fade`

Fade the current slide into the next one.

[![asciicast](https://asciinema.org/a/RvxLw0FHOopjdF4ixWbCkWuSw.svg)](https://asciinema.org/a/RvxLw0FHOopjdF4ixWbCkWuSw)

## `slide_horizontal`

Slide horizontally to the next/previous slide.

[![asciicast](https://asciinema.org/a/T43ttxPWZ8TsM2auTqNZSWrmZ.svg)](https://asciinema.org/a/T43ttxPWZ8TsM2auTqNZSWrmZ)

## `collapse_horizontal`

Collapse the current slide into the center of the screen horizontally.

[![asciicast](https://asciinema.org/a/VB8i3kGMvbkbiYYPpaZJUl2dW.svg)](https://asciinema.org/a/VB8i3kGMvbkbiYYPpaZJUl2dW)


================================================
FILE: docs/src/features/speaker-notes.md
================================================
## Speaker notes

Starting on version 0.10.0, _presenterm_ allows presentations to define speaker notes. The way this works is:

* You start an instance of _presenterm_ using the `--publish-speaker-notes` parameter. This will be the main instance in 
which you will present like you usually do.
* Another instance should be started using the `--listen-speaker-notes` parameter. This instance will only display 
speaker notes in the presentation and will automatically change slides whenever the main instance does so.

For example:

```bash
# Start the main instance
presenterm demo.md --publish-speaker-notes

# In another shell: start the speaker notes instance
presenterm demo.md --listen-speaker-notes
```

[![asciicast](https://asciinema.org/a/ETusvlmHuHrcLKzwa0CMQRX2J.svg)](https://asciinema.org/a/ETusvlmHuHrcLKzwa0CMQRX2J)

See the [speaker notes example](https://github.com/mfontanini/presenterm/blob/master/examples/speaker-notes.md) for more 
information.

### Defining speaker notes

In order to define speaker notes you can use the `speaker_notes` comment command:

```markdown
Normal text

<!-- speaker_note: this is a speaker note -->

More text
```

When running this two instance setup, the main one will show "normal text" and "more text", whereas the second one will 
only show "this is a speaker note" on that slide.

### Multiline speaker notes

You can use multiline speaker notes by using the appropriate YAML syntax:

```yaml
<!-- 
speaker_note: |
  something
  something else
-->
```

### Multiple instances

On Linux and Windows, you can run multiple instances in publish mode and multiple instances in listen mode at the same 
time. Each instance will only listen to events for the presentation it was started on.

On Mac this is not supported and only a single listener can be used at a time.

### Enabling publishing by default

You can use the `speaker_notes.always_publish` key in your config file to always publish speaker notes. This means you 
will only ever need to use `--listen-speaker-notes` and you will never need to use `--publish-speaker-notes`:

```yaml
speaker_notes:
  always_publish: true
```

### Internals

This uses UDP sockets on localhost to communicate between instances. The main instance sends events every time a slide 
is shown and the listener instances listen to them and displays the speaker notes for that specific slide.


================================================
FILE: docs/src/features/themes/definition.md
================================================
# Theme definition

This section goes through the structure of the theme files. Have a look at some of the [existing 
themes](https://github.com/mfontanini/presenterm/tree/master/themes) to have an idea of how to structure themes. 

## Root elements

The root attributes on the theme yaml files specify either:

* A specific type of element in the input markdown or rendered presentation. That is, the slide title, headings, footer, 
  etc.
* A default to be applied as a fallback if no specific style is specified for a particular element.

## Alignment

_presenterm_ uses the notion of alignment, just like you would have in a GUI editor, to align text to the left, center, 
or right. You probably want most elements to be aligned left, _some_ to be aligned on the center, and probably none to 
the right (but hey, you're free to do so!).

The following elements support alignment:
* Code blocks.
* Slide titles.
* The title, subtitle, and author elements in the intro slide.
* Tables.

### Left/right alignment

Left and right alignments take a margin property which specifies the number of columns to keep between the text and the 
left/right terminal screen borders. 

The margin can be specified in two ways:

#### Fixed

A specific number of characters regardless of the terminal size.

```yaml
alignment: left
margin:
  fixed: 5
```

#### Percent

A percentage over the total number of columns in the terminal.

```yaml
alignment: left
margin:
  percent: 8
```

Percent alignment tends to look a bit nicer as it won't change the presentation's look as much when the terminal size 
changes.

### Center alignment

Center alignment has 2 properties:
* `minimum_size` which specifies the minimum size you want that element to have. This is normally useful for code blocks 
  as they have a predefined background which you likely want to extend slightly beyond the end of the code on the right.
* `minimum_margin` which specifies the minimum margin you want, using the same structure as `margin` for left/right 
  alignment. This doesn't play very well with `minimum_size` but in isolation it specifies the minimum number of columns 
  you want to the left and right of your text.

## Colors

Every element can have its own background/foreground color using hex notation:

```yaml
default:
  colors:
    foreground: ff0000
    background: 00ff00
```

## Default style

The default style specifies:

* The margin to be applied to all slides.
* The colors to be used for all text.

```yaml
default:
  margin:
    percent: 8
  colors:
    foreground: "e6e6e6"
    background: "040312"
```

## Intro slide

The introductory slide will be rendered if you specify a title, subtitle, or author in the presentation's front matter. 
This lets you have a less markdown-looking introductory slide that stands out so that it doesn't end up looking too 
monotonous:

```yaml
---
title: Presenting from my terminal
sub_title: Like it's 1990
author: John Doe
---
```

The theme can specify:
* For the title and subtitle, the alignment and colors.
* For the author, the alignment, colors, and positioning (`page_bottom` and `below_title`). The first one will push it 
  to the bottom of the screen while the second one will put it right below the title (or subtitle if there is one)

For example:

```yaml
intro_slide:
  title:
    alignment: left
    margin:
      percent: 8
  author:
    colors:
      foreground: black
    positioning: below_title
```

## Footer

The footer currently comes in 3 flavors:

### Template footers

A template footer lets you put text on the left, center and/or right of the screen. The template strings
can reference `{current_slide}` and `{total_slides}` which will be replaced with the current and total number of slides.

Besides those special variables, any of the attributes defined in the front matter can also be used:

* `title`.
* `sub_title`.
* `event`.
* `location`.
* `date`.
* `author`.

Strings used in template footers can contain arbitrary markdown, including `span` tags that let you use colored text. A 
`height` attribute allows specifying how tall, in terminal rows, the footer is. The text in the footer will always be 
placed at the center of the footer area. The default footer height is 2.

```yaml
footer:
  style: template
  left: "My **name** is {author}"
  center: "_@myhandle_"
  right: "{current_slide} / {total_slides}"
  height: 3
```

Do note that:

* Only existing attributes in the front matter can be referenced. That is, if you use `{date}` but the `date` isn't set, 
an error will be shown.
* Similarly, referencing unsupported variables (e.g. `{potato}`) will cause an error to be displayed. If you'd like the 
`{}` characters to be used in contexts where you don't want to reference a variable, you will need to escape them by 
using another brace. e.g. `{{potato}} farms` will be displayed as `{potato} farms`.

#### Footer images

Besides text, images can also be used in the left/center/right positions. This can be done by specifying an `image` key 
under each of those attributes:

```yaml
footer:
  style: template
  left:
    image: potato.png
  center:
    image: banana.png
  right:
    image: apple.png
  # The height of the footer to adjust image sizes
  height: 5
```

Images will be looked up:

* First, relative to the presentation file just like any other image.
* If the image is not found, it will be looked up relative to the themes directory. e.g. `~/.config/presenterm/themes`. 
This allows you to define a custom theme in your themes directory that points to a local image within that same 
location.

Images will preserve their aspect ratio and expand vertically to take up as many terminal rows as `footer.height` 
specifies. This parameter should be adjusted accordingly if taller-than-wider images are used in a footer.

See the [footer example](https://github.com/mfontanini/presenterm/blob/master/examples/footer.md) as a showcase of how a 
footer can contain images and colored text.

![](../../assets/example-footer.png)

### Progress bar footers

A progress bar that will advance as you move in your presentation. This will by default use a block-looking character to 
draw the progress bar but you can customize it:

```yaml
footer:
  style: progress_bar

  # Optional!
  character: 🚀
```

### None

No footer at all!

```yaml
footer:
  style: empty
```


## Slide title

Slide titles, as specified by using a setext header, can be styled the following way:

```yaml
slide_title:
  # The prefix to use for the slide title.
  prefix: "██"

  # The font size to use.
  font_size: 2

  # The vertical padding added before the title.
  padding_top: 1

  # The vertical padding added after the title.
  padding_bottom: 1

  # Whether to use a horizontal separator line after the title.
  separator: true

  # Whether to style for the title using bold text.
  bold: true

  # Whether to style for the title using underlined text.
  underlined: true

  # Whether to style for the title using italics text.
  italics: true

  # The colors to use.
  colors:
    foreground: beeeff
    background: feeedd
```

## Headings

Every header type (h1 through h6) can have its own style. Each of them can be styled using the following attributes:

```yaml
headings:
  # H1 style.
  h1:
    # The prefix to use for the heading
    prefix: "██"

    # The colors to use.
    colors:
      foreground: beeeff
      background: feeedd
    # Whether to style for the title using bold text.
    bold: true

    # Whether to style for the title using underlined text.
    underlined: true

    # Whether to style for the title using italics text.
    italics: true
  
  # H2 style, same as the keys for H1.
  h2:
    prefix: "▓▓▓"
    colors:
      foreground: feeedd
```

## Code blocks

The syntax highlighting for code blocks is done via the [syntect](https://github.com/trishume/syntect) crate. The list 
of all the supported themes is the following:

* base16-ocean.dark
* base16-eighties.dark
* base16-mocha.dark
* base16-ocean.light
* Catppuccin
* Coldark
* DarkNeon
* InspiredGitHub
* Nord-sublime
* Solarized
* Solarized (dark)
* Solarized (light)
* TwoDark
* dracula-sublime
* github-sublime-theme
* gruvbox
* onehalf
* sublime-monokai-extended
* sublime-snazzy
* visual-studio-dark-plus
* zenburn

Most of these are taken from the [bat tool](https://github.com/sharkdp/bat), thanks to the people behind `bat` for 
implementing them!

Code blocks can also have a few additional properties:

```yaml
code:
  # The code theme.
  theme_name: base16-eighties.dark

  # The padding to be applied, in cells, around a code snippet.
  padding:
    horizontal: 2
    vertical: 1

  # Whether the theme's background color should be used around the code block.
  background: false

  # Whether to set line numbers in all snippets by default.
  line_numbers: false
```

#### Custom highlighting themes

Besides the built-in highlighting themes, you can drop any `.tmTheme` theme in the `themes/highlighting` directory under 
your [configuration directory](../../configuration/introduction.md) (e.g. `~/.config/presenterm/themes/highlighting` in 
Linux) and they will be loaded automatically when _presenterm_ starts.

## Block quotes

For block quotes you can specify a string to use as a prefix in every line of quoted text:

```yaml
block_quote:
  prefix: "▍ "
```

## Mermaid

The [mermaid](https://mermaid.js.org/) graphs can be customized using the following parameters:

* `mermaid.background` the background color passed to the CLI (e.g., `transparent`, `red`, `#F0F0F0`).
* `mermaid.theme` the [mermaid theme](https://mermaid.js.org/config/theming.html#available-themes) to use.

```yaml
mermaid:
  background: transparent
  theme: dark
```

## Alerts

GitHub style markdown alerts can be styled by setting the `alert` key:

```yaml
alert:
  # the base colors used in all text in an alert
  base_colors:
    foreground: red
    background: black

  # the prefix used in every line in the alert
  prefix: "▍ "

  # the style for each alert type
  styles:
    note:
      color: blue
      title: Note
      icon: I
    tip:
      color: green
      title: Tip
      icon: T
    important:
      color: cyan
      title: Important
      icon: I
    warning:
      color: orange
      title: Warning
      icon: W
    caution:
      color: red
      title: Caution
      icon: C
```

## Extending themes

Custom themes can extend other custom or built in themes. This means it will inherit all the properties of the theme 
being extended by default.

For example:

```yaml
extends: dark
default:
  colors:
    background: "000000"
```

This theme extends the built in _dark_ theme and overrides the background color. This is useful if you find yourself 
_almost_ liking a built in theme but there's only some properties you don't like.

## Color palette

Every theme can define a color palette, which includes a list of pre-defined colors and a list of background/foreground 
pairs called "classes". Colors and classes can be used when styling text via `<span>` HTML tags, whereas colors can also 
be used inside themes to avoid duplicating the same colors all over the theme definition.

A palette can de defined as follows:

```yaml
palette:
  colors:
    red: "f78ca2"
    purple: "986ee2"
  classes:
    foo:
      foreground: "ff0000"
      background: "00ff00"
```

Any palette color can be referenced using either `palette:<name>` or `p:<name>`. This means now any part of the theme 
can use `p:red` and `p:purple` where a color is required.

Similarly, these colors can be used in `span` tags like:

```html
<span style="color: palette:red">this is red</span>

<span class="foo">this is foo-colored</span>
```

These colors can used anywhere in your presentation as well as in other places such as in
[template footers](#template-footers) and [introduction slides](../introduction.md#introduction-slide).

## Bold/italics styling

Bold and italics text is not given any colors by default. The `bold` and `italics` top level keys can be used to define 
a set of colors to use for them:

```yaml
bold:
  colors:
    foreground: red
italics:
  colors:
    background: blue
```


================================================
FILE: docs/src/features/themes/introduction.md
================================================
# Themes

_presenterm_ tries to be as configurable as possible, allowing users to create presentations that look exactly how they 
want them to look like. The tool ships with a set of [built-in 
themes](https://github.com/mfontanini/presenterm/tree/master/themes) but users can be created by users in their local 
setup and imported in their presentations.

## Setting themes

There's various ways of setting the theme you want in your presentation:

### CLI

Passing in the `--theme` parameter when running _presenterm_ to select one of the built-in themes.

### Within the presentation

The presentation's markdown file can contain a front matter that specifies the theme to use. This comes in 3 flavors:

#### By name

Using a built-in theme name makes your presentation use that one regardless of what the default or what the `--theme` 
option specifies:

```yaml
---
theme:
  name: dark
---
```

Built-in light/dark theme detection allows you to define a different theme for each variant:


```yaml
---
theme:
  # The theme used if your terminal is using light colors.
  light: light

  # The theme used if your terminal is using dark colors.
  dark: dark
---
```

#### By path

You can define a theme file in yaml format somewhere in your filesystem and reference it within the presentation:

```yaml
---
theme:
  path: /home/me/Documents/epic-theme.yaml
---
```

#### Overrides

You can partially/completely override the theme in use from within the presentation:

```yaml
---
theme:
  overrid
Download .txt
gitextract_hsyzsbc9/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── docs.yaml
│       ├── merge.yaml
│       ├── nightly.yaml
│       └── release.yaml
├── .gitignore
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── bat/
│   ├── acknowledgements.txt
│   ├── bat.git-hash
│   ├── syntaxes.git-hash
│   ├── update.sh
│   └── verify.sh
├── build.rs
├── config-file-schema.json
├── config.sample.yaml
├── docs/
│   ├── .gitignore
│   ├── book.toml
│   └── src/
│       ├── SUMMARY.md
│       ├── acknowledgements.md
│       ├── configuration/
│       │   ├── introduction.md
│       │   ├── options.md
│       │   └── settings.md
│       ├── features/
│       │   ├── code/
│       │   │   ├── d2.md
│       │   │   ├── execution.md
│       │   │   ├── highlighting.md
│       │   │   ├── latex.md
│       │   │   └── mermaid.md
│       │   ├── commands.md
│       │   ├── exports.md
│       │   ├── images.md
│       │   ├── introduction.md
│       │   ├── layout.md
│       │   ├── slide-transitions.md
│       │   ├── speaker-notes.md
│       │   └── themes/
│       │       ├── definition.md
│       │       └── introduction.md
│       ├── install.md
│       ├── internals/
│       │   └── parse.md
│       └── introduction.md
├── examples/
│   ├── README.md
│   ├── code.md
│   ├── columns.md
│   ├── custom-intro-slides.md
│   ├── demo.md
│   ├── footer.md
│   └── speaker-notes.md
├── executors.yaml
├── flake.nix
├── rustfmt.toml
├── scripts/
│   ├── generate-config-file-schema.sh
│   ├── parse-changelog.sh
│   ├── test-pdf-generation.sh
│   └── validate-config-file-schema.sh
├── src/
│   ├── code/
│   │   ├── execute.rs
│   │   ├── highlighting.rs
│   │   ├── mod.rs
│   │   ├── padding.rs
│   │   └── snippet.rs
│   ├── commands/
│   │   ├── keyboard.rs
│   │   ├── listener.rs
│   │   ├── mod.rs
│   │   └── speaker_notes.rs
│   ├── config.rs
│   ├── demo.rs
│   ├── export/
│   │   ├── exporter.rs
│   │   ├── html.rs
│   │   ├── mod.rs
│   │   ├── output.rs
│   │   └── script.js
│   ├── main.rs
│   ├── markdown/
│   │   ├── elements.rs
│   │   ├── html.rs
│   │   ├── mod.rs
│   │   ├── parse.rs
│   │   ├── text.rs
│   │   └── text_style.rs
│   ├── presentation/
│   │   ├── builder/
│   │   │   ├── comment.rs
│   │   │   ├── error.rs
│   │   │   ├── frontmatter.rs
│   │   │   ├── heading.rs
│   │   │   ├── images.rs
│   │   │   ├── list.rs
│   │   │   ├── mod.rs
│   │   │   ├── quote.rs
│   │   │   ├── snippet.rs
│   │   │   ├── sources.rs
│   │   │   ├── table.rs
│   │   │   └── tests.rs
│   │   ├── diff.rs
│   │   ├── mod.rs
│   │   └── poller.rs
│   ├── presenter.rs
│   ├── render/
│   │   ├── ascii_scaler.rs
│   │   ├── engine.rs
│   │   ├── layout.rs
│   │   ├── mod.rs
│   │   ├── operation.rs
│   │   ├── properties.rs
│   │   ├── text.rs
│   │   └── validate.rs
│   ├── resource.rs
│   ├── terminal/
│   │   ├── ansi.rs
│   │   ├── capabilities.rs
│   │   ├── emulator.rs
│   │   ├── image/
│   │   │   ├── mod.rs
│   │   │   ├── printer.rs
│   │   │   ├── protocols/
│   │   │   │   ├── ascii.rs
│   │   │   │   ├── iterm.rs
│   │   │   │   ├── kitty.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── raw.rs
│   │   │   │   └── sixel.rs
│   │   │   └── scale.rs
│   │   ├── mod.rs
│   │   ├── printer.rs
│   │   └── virt.rs
│   ├── theme/
│   │   ├── clean.rs
│   │   ├── mod.rs
│   │   ├── raw.rs
│   │   └── registry.rs
│   ├── third_party.rs
│   ├── tools.rs
│   ├── transitions/
│   │   ├── collapse_horizontal.rs
│   │   ├── fade.rs
│   │   ├── mod.rs
│   │   └── slide_horizontal.rs
│   ├── ui/
│   │   ├── execution/
│   │   │   ├── acquire_terminal.rs
│   │   │   ├── disabled.rs
│   │   │   ├── image.rs
│   │   │   ├── mod.rs
│   │   │   ├── output.rs
│   │   │   ├── pty.rs
│   │   │   └── validator.rs
│   │   ├── footer.rs
│   │   ├── mod.rs
│   │   ├── modals.rs
│   │   └── separator.rs
│   └── utils.rs
└── themes/
    ├── catppuccin-frappe.yaml
    ├── catppuccin-latte.yaml
    ├── catppuccin-macchiato.yaml
    ├── catppuccin-mocha.yaml
    ├── dark.yaml
    ├── gruvbox-dark.yaml
    ├── light.yaml
    ├── terminal-dark.yaml
    ├── terminal-light.yaml
    ├── tokyonight-day.yaml
    ├── tokyonight-moon.yaml
    ├── tokyonight-night.yaml
    └── tokyonight-storm.yaml
Download .txt
SYMBOL INDEX (1794 symbols across 78 files)

FILE: build.rs
  function build_themes (line 9) | fn build_themes(out_dir: &str) -> io::Result<()> {
  function main (line 37) | fn main() -> io::Result<()> {

FILE: src/code/execute.rs
  function strip_drive_unc_prefix (line 27) | fn strip_drive_unc_prefix(path: &Path) -> String {
  type SnippetExecutor (line 44) | pub struct SnippetExecutor {
    method new (line 50) | pub fn new(
    method language_executor (line 65) | pub(crate) fn language_executor(
    method hidden_line_prefix (line 89) | pub(crate) fn hidden_line_prefix(&self, language: &SnippetLanguage) ->...
    method validate_executor_config (line 93) | fn validate_executor_config(
  method default (line 113) | fn default() -> Self {
  method fmt (line 119) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type LanguageSnippetExecutor (line 125) | pub(crate) struct LanguageSnippetExecutor {
    method execute_async (line 133) | pub(crate) fn execute_async(&self, snippet: &Snippet) -> Result<Execut...
    method execute_sync (line 153) | pub(crate) fn execute_sync(&self, snippet: &Snippet) -> Result<(), Cod...
    method pty_execution_context (line 163) | pub(crate) fn pty_execution_context(&self, snippet: &Snippet) -> Resul...
    method execute_command (line 186) | fn execute_command(&self, mut commands: Vec<String>, script_dir_path: ...
    method write_snippet (line 208) | fn write_snippet(&self, snippet: &Snippet) -> Result<TempDir, CodeExec...
  type PtySnippetContext (line 220) | pub(crate) struct PtySnippetContext {
  type InvalidSnippetConfig (line 228) | pub struct InvalidSnippetConfig(SnippetLanguage, &'static str);
  type UnsupportedExecution (line 233) | pub struct UnsupportedExecution(SnippetLanguage, String);
  type CodeExecuteError (line 237) | pub(crate) enum CodeExecuteError {
  type ExecutionHandle (line 256) | pub(crate) struct ExecutionHandle {
  type CommandsRunner (line 263) | struct CommandsRunner {
    method spawn (line 269) | fn spawn(
    method run (line 281) | fn run(self, commands: Vec<Vec<String>>, env: HashMap<String, String>,...
    method run_command (line 296) | fn run_command(
    method launch_process (line 320) | fn launch_process(
    method process_output (line 349) | fn process_output(
  type OutputType (line 375) | enum OutputType {
  type ExecutionState (line 382) | pub(crate) struct ExecutionState {
  type ProcessStatus (line 389) | pub(crate) enum ProcessStatus {
    method is_finished (line 398) | pub(crate) fn is_finished(&self) -> bool {
  function shell_code_execution (line 409) | fn shell_code_execution() {
  function shell_code_execution_captures_stderr (line 436) | fn shell_code_execution_captures_stderr() {
  function shell_code_execution_executes_hidden_lines (line 464) | fn shell_code_execution_executes_hidden_lines() {
  function built_in_executors (line 493) | fn built_in_executors() {

FILE: src/code/highlighting.rs
  type LazyThemeSet (line 33) | struct LazyThemeSet {
  type HighlightThemeSet (line 37) | pub struct HighlightThemeSet {
    method load_by_name (line 43) | pub fn load_by_name(&self, name: &str) -> Option<SnippetHighlighter> {
    method register_from_directory (line 59) | pub fn register_from_directory<P: AsRef<Path>>(&mut self, path: P) -> ...
    method deserialize_bat_theme (line 72) | fn deserialize_bat_theme(&self, name: &str) -> Option<Rc<Theme>> {
  method default (line 81) | fn default() -> Self {
  type SnippetHighlighter (line 90) | pub(crate) struct SnippetHighlighter {
    method language_highlighter (line 96) | pub(crate) fn language_highlighter(&self, language: &SnippetLanguage) ...
    method language_extension (line 103) | fn language_extension(language: &SnippetLanguage) -> &'static str {
  method default (line 185) | fn default() -> Self {
  type LanguageHighlighter (line 191) | pub(crate) struct LanguageHighlighter<'a> {
  function new (line 198) | fn new(language: SnippetLanguage, highlighter: HighlightLines<'a>) -> Se...
  function style_line (line 202) | pub(crate) fn style_line(&mut self, line: &str, block_style: &CodeBlockS...
  type StyledTokens (line 225) | pub(crate) struct StyledTokens<'a> {
  function new (line 231) | pub(crate) fn new(style: Style, tokens: &'a str, block_style: &CodeBlock...
  function apply_style (line 241) | pub(crate) fn apply_style(&self) -> Text {
  function parse_color (line 248) | fn parse_color(color: syntect::highlighting::Color) -> Option<Color> {
  function language_extensions_exist (line 283) | fn language_extensions_exist() {
  function default_highlighter (line 292) | fn default_highlighter() {
  function load_custom (line 297) | fn load_custom() {
  function register_from_missing_directory (line 323) | fn register_from_missing_directory() {
  function default_themes (line 330) | fn default_themes() {

FILE: src/code/padding.rs
  type NumberPadder (line 3) | pub(crate) struct NumberPadder {
    method new (line 8) | pub(crate) fn new(upper_bound: usize) -> Self {
    method pad_right (line 13) | pub(crate) fn pad_right(&self, number: usize) -> String {
  function right_padding (line 34) | fn right_padding(#[case] numbers: &[usize], #[case] expected: &[&str]) {
  function zero_count (line 42) | fn zero_count() {

FILE: src/code/snippet.rs
  type SnippetSplitter (line 23) | pub(crate) struct SnippetSplitter<'a> {
  function new (line 29) | pub(crate) fn new(style: &'a CodeBlockStyle, hidden_line_prefix: Option<...
  function split (line 33) | pub(crate) fn split(&self, code: &Snippet) -> Vec<SnippetLine> {
  function push_lines (line 47) | fn push_lines(&self, code: &Snippet, horizontal_padding: u8, lines: &mut...
  type SnippetLine (line 69) | pub(crate) struct SnippetLine {
    method empty (line 77) | pub(crate) fn empty() -> Self {
    method width (line 81) | pub(crate) fn width(&self) -> usize {
    method highlight (line 85) | pub(crate) fn highlight(
    method dim (line 96) | pub(crate) fn dim(&self, dim_style: &TextStyle) -> WeightedLine {
    method dim_prefix (line 101) | pub(crate) fn dim_prefix(&self, dim_style: &TextStyle) -> WeightedText {
  type HighlightContext (line 108) | pub(crate) struct HighlightContext {
  type HighlightedLine (line 116) | pub(crate) struct HighlightedLine {
  method as_render_operations (line 127) | fn as_render_operations(&self, _: &WindowSize) -> Vec<RenderOperation> {
  type HighlightMutator (line 152) | pub(crate) struct HighlightMutator {
    method new (line 157) | pub(crate) fn new(context: Rc<RefCell<HighlightContext>>) -> Self {
  method mutate_next (line 163) | fn mutate_next(&self) -> bool {
  method mutate_previous (line 173) | fn mutate_previous(&self) -> bool {
  method reset_mutations (line 183) | fn reset_mutations(&self) {
  method apply_all_mutations (line 187) | fn apply_all_mutations(&self) {
  method mutations (line 192) | fn mutations(&self) -> (usize, usize) {
  type ParseResult (line 198) | pub(crate) type ParseResult<T> = Result<T, SnippetBlockParseError>;
  type SnippetParser (line 200) | pub(crate) struct SnippetParser;
    method parse (line 203) | pub(crate) fn parse(info: String, code: String) -> ParseResult<Snippet> {
    method parse_block_info (line 209) | fn parse_block_info(input: &str) -> ParseResult<(SnippetLanguage, Snip...
    method parse_language (line 218) | fn parse_language(input: &str) -> (SnippetLanguage, &str) {
    method parse_attributes (line 226) | fn parse_attributes(mut input: &str) -> ParseResult<SnippetAttributes> {
    method parse_attribute (line 302) | fn parse_attribute(input: &str) -> ParseResult<(Option<SnippetAttribut...
    method parse_highlight_groups (line 371) | fn parse_highlight_groups(input: &str) -> ParseResult<(Vec<HighlightGr...
    method parse_highlight_group (line 389) | fn parse_highlight_group(input: &str) -> ParseResult<HighlightGroup> {
    method parse_number (line 415) | fn parse_number(input: &str) -> ParseResult<u16> {
    method skip_whitespace (line 422) | fn skip_whitespace(input: &str) -> &str {
    method next_identifier (line 426) | fn next_identifier(input: &str) -> &str {
  type SnippetBlockParseError (line 435) | pub enum SnippetBlockParseError {
  type SnippetAttribute (line 459) | enum SnippetAttribute {
  type SnippetExecutorSpec (line 477) | pub(crate) enum SnippetExecutorSpec {
  type ExpectedSnippetExecutionResult (line 484) | pub(crate) enum ExpectedSnippetExecutionResult {
  type Snippet (line 492) | pub(crate) struct Snippet {
    method visible_lines (line 504) | pub(crate) fn visible_lines<'a, 'b>(
    method executable_contents (line 514) | pub(crate) fn executable_contents(&self, hidden_line_prefix: Option<&s...
  type SnippetLanguage (line 530) | pub enum SnippetLanguage {
  type Err (line 609) | type Err = Infallible;
  method from_str (line 611) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type SnippetAttributes (line 694) | pub(crate) struct SnippetAttributes {
  type SnippetRepr (line 723) | pub(crate) enum SnippetRepr {
  type PtyArgs (line 732) | pub(crate) struct PtyArgs {
  type Err (line 739) | type Err = SnippetBlockParseError;
  method from_str (line 741) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type SnippetExecArgs (line 768) | pub(crate) struct SnippetExecArgs {
  type SnippetExecution (line 776) | pub(crate) enum SnippetExecution {
    method try_merge (line 784) | fn try_merge(self, other: SnippetExecution) -> ParseResult<Self> {
  type HighlightGroup (line 813) | pub(crate) struct HighlightGroup(Vec<Highlight>);
    method new (line 816) | pub(crate) fn new(highlights: Vec<Highlight>) -> Self {
    method contains (line 820) | pub(crate) fn contains(&self, line_number: u16) -> bool {
  type Highlight (line 835) | pub(crate) enum Highlight {
  type ExternalFile (line 842) | pub(crate) struct ExternalFile {
  function parse_language (line 855) | fn parse_language(input: &str) -> SnippetLanguage {
  function try_parse_attributes (line 860) | fn try_parse_attributes(input: &str) -> Result<SnippetAttributes, Snippe...
  function parse_attributes (line 865) | fn parse_attributes(input: &str) -> SnippetAttributes {
  function code_with_line_numbers (line 870) | fn code_with_line_numbers() {
  function unknown_language (line 895) | fn unknown_language() {
  function no_attributes (line 900) | fn no_attributes() {
  function one_attribute (line 905) | fn one_attribute() {
  function two_attributes (line 912) | fn two_attributes() {
  function acquire_terminal (line 919) | fn acquire_terminal() {
  function image (line 929) | fn image() {
  function invalid_attributes (line 939) | fn invalid_attributes() {
  function invalid_line_highlights (line 955) | fn invalid_line_highlights(#[case] input: &str) {
  function highlight_none (line 961) | fn highlight_none() {
  function highlight_specific_lines (line 967) | fn highlight_specific_lines() {
  function highlight_line_range (line 973) | fn highlight_line_range() {
  function multiple_groups (line 982) | fn multiple_groups() {
  function parse_width (line 990) | fn parse_width() {
  function invalid_width (line 997) | fn invalid_width() {
  function code_visible_lines (line 1004) | fn code_visible_lines() {
  function code_executable_contents (line 1018) | fn code_executable_contents() {
  function tabs_in_snippet (line 1038) | fn tabs_in_snippet() {
  function alternative_executor (line 1049) | fn alternative_executor(#[case] input: &str, #[case] spec: SnippetExecut...
  function acquire_terminal_alternative (line 1056) | fn acquire_terminal_alternative() {
  function parse_expect (line 1072) | fn parse_expect(#[case] input: &str, #[case] expected: ExpectedSnippetEx...

FILE: src/commands/keyboard.rs
  type KeyboardListener (line 7) | pub struct KeyboardListener {
    method new (line 13) | pub fn new(bindings: CommandKeyBindings) -> Self {
    method poll_next_command (line 18) | pub(crate) fn poll_next_command(&mut self, timeout: Duration) -> io::R...
    method next_command (line 23) | pub(crate) fn next_command(&mut self) -> io::Result<Option<Command>> {
    method match_events (line 39) | fn match_events(&self, events: Vec<KeyEvent>) -> (Option<Command>, Vec...
  type InputAction (line 48) | enum InputAction {
  type CommandKeyBindings (line 54) | pub struct CommandKeyBindings {
    method apply (line 59) | fn apply(&self, events: &[KeyEvent]) -> InputAction {
    method instantiate (line 71) | fn instantiate(discriminant: &CommandDiscriminants, context: MatchCont...
    method validate_conflicts (line 104) | fn validate_conflicts<'a>(
    type Error (line 122) | type Error = KeyBindingsValidationError;
    method try_from (line 124) | fn try_from(config: KeyBindingsConfig) -> Result<Self, Self::Error> {
  type KeyBindingsValidationError (line 171) | pub enum KeyBindingsValidationError {
  type BindingMatch (line 180) | enum BindingMatch {
  type KeyBinding (line 188) | pub struct KeyBinding(#[cfg_attr(feature = "json-schema", schemars(with ...
    method match_events (line 193) | fn match_events(&self, mut events: &[KeyEvent]) -> BindingMatch {
    method expects_number (line 213) | fn expects_number(&self) -> bool {
    method fmt (line 240) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Err (line 219) | type Err = KeyBindingParseError;
  method from_str (line 221) | fn from_str(mut input: &str) -> Result<Self, Self::Err> {
  type KeyBindingParseError (line 249) | pub enum KeyBindingParseError {
  type KeyMatcher (line 264) | enum KeyMatcher {
    method try_match_events (line 270) | fn try_match_events<'a>(&self, events: &'a [KeyEvent]) -> Option<(Matc...
    method try_match_key (line 277) | fn try_match_key<'a>(combo: &KeyCombination, events: &'a [KeyEvent]) -...
    method try_match_number (line 288) | fn try_match_number(mut events: &[KeyEvent]) -> Option<(MatchContext, ...
    method parse (line 309) | fn parse(input: &str) -> Result<(Self, &str), KeyBindingParseError> {
    method parse_key_code (line 326) | fn parse_key_code(input: &str) -> Result<(KeyCode, &str), KeyBindingPa...
    method try_match_input (line 369) | fn try_match_input<'a>(input: &'a str, aliases: &[&str]) -> Option<&'a...
    method fmt (line 380) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type MatchContext (line 402) | enum MatchContext {
  type KeyCombination (line 408) | struct KeyCombination {
    method char (line 415) | fn char(c: char) -> Self {
    method control_char (line 420) | fn control_char(c: char) -> Self {
    method from (line 426) | fn from(key: KeyCode) -> Self {
  type KeyEventSource (line 437) | trait KeyEventSource {
    method into_event (line 438) | fn into_event(self) -> KeyEvent;
    method into_event (line 442) | fn into_event(self) -> KeyEvent {
    method into_event (line 453) | fn into_event(self) -> KeyEvent {
  type KeyEventExt (line 458) | trait KeyEventExt {
    method with_control (line 459) | fn with_control(self) -> Self;
    method with_control (line 463) | fn with_control(mut self) -> Self {
  function parse_key_binding (line 504) | fn parse_key_binding(#[case] pattern: &str, #[case] matchers: Vec<KeyMat...
  function invalid_key_bindings (line 517) | fn invalid_key_bindings(#[case] input: &str) {
  function matching (line 533) | fn matching(#[case] pattern: &str, #[case] events: &[KeyEvent]) {
  function partial_matching (line 544) | fn partial_matching(#[case] pattern: &str, #[case] events: &[KeyEvent]) {
  function no_matching (line 552) | fn no_matching(#[case] pattern: &str, #[case] events: &[KeyEvent]) {
  function match_number (line 564) | fn match_number(#[case] pattern: &str, #[case] events: &[KeyEvent]) {
  function conflicts (line 580) | fn conflicts(#[case] patterns: &[&str]) {
  function no_conflicts (line 589) | fn no_conflicts(#[case] patterns: &[&str]) {
  function display (line 599) | fn display(#[case] pattern: &str) {

FILE: src/commands/listener.rs
  type CommandListener (line 11) | pub struct CommandListener {
    method new (line 18) | pub fn new(
    method try_next_command (line 29) | pub(crate) fn try_next_command(&mut self) -> Result<Option<Command>, P...
  type Command (line 49) | pub(crate) enum Command {

FILE: src/commands/speaker_notes.rs
  type SpeakerNotesEventPublisher (line 9) | pub struct SpeakerNotesEventPublisher {
    method new (line 15) | pub fn new(address: SocketAddr, presentation_path: PathBuf) -> io::Res...
    method send (line 22) | pub(crate) fn send(&self, event: SpeakerNotesEvent) -> io::Result<()> {
  type SpeakerNotesEventListener (line 35) | pub struct SpeakerNotesEventListener {
    method new (line 41) | pub fn new(address: SocketAddr, presentation_path: PathBuf) -> io::Res...
    method try_recv (line 52) | pub(crate) fn try_recv(&self) -> io::Result<Option<SpeakerNotesEvent>> {
  type SpeakerNotesEvent (line 70) | pub(crate) enum SpeakerNotesEvent {
  type SpeakerNotesEventEnvelope (line 76) | struct SpeakerNotesEventEnvelope {
  function make_listener (line 88) | fn make_listener(path: PathBuf) -> SpeakerNotesEventListener {
  function make_publisher (line 92) | fn make_publisher(path: PathBuf) -> SpeakerNotesEventPublisher {
  function bind_multiple (line 97) | fn bind_multiple() {
  function multicast (line 103) | fn multicast() {

FILE: src/config.rs
  type Config (line 19) | pub struct Config {
    method load (line 54) | pub fn load(path: &Path) -> Result<Self, ConfigLoadError> {
  type ConfigLoadError (line 66) | pub enum ConfigLoadError {
  type ThemeConfig (line 82) | pub enum ThemeConfig {
  type DefaultsConfig (line 102) | pub struct DefaultsConfig {
  method default (line 148) | fn default() -> Self {
  type IncrementalElementConfig (line 168) | pub struct IncrementalElementConfig {
  function default_terminal_font_size (line 178) | fn default_terminal_font_size() -> u8 {
  type MaxColumnsAlignment (line 186) | pub enum MaxColumnsAlignment {
  type MaxRowsAlignment (line 202) | pub enum MaxRowsAlignment {
  type ValidateOverflows (line 217) | pub enum ValidateOverflows {
  type OptionsConfig (line 228) | pub struct OptionsConfig {
  type SnippetConfig (line 264) | pub struct SnippetConfig {
  type SnippetExecConfig (line 285) | pub struct SnippetExecConfig {
  type SnippetExecReplaceConfig (line 298) | pub struct SnippetExecReplaceConfig {
  type SnippetRenderConfig (line 307) | pub struct SnippetRenderConfig {
  method default (line 314) | fn default() -> Self {
  function default_snippet_render_threads (line 319) | pub(crate) fn default_snippet_render_threads() -> usize {
  type TypstConfig (line 326) | pub struct TypstConfig {
  method default (line 333) | fn default() -> Self {
  function default_typst_ppi (line 338) | pub(crate) fn default_typst_ppi() -> u32 {
  type MermaidConfig (line 345) | pub struct MermaidConfig {
  method default (line 358) | fn default() -> Self {
  function default_mermaid_scale (line 363) | pub(crate) fn default_mermaid_scale() -> u32 {
  type D2Config (line 370) | pub struct D2Config {
  function default_u16_max (line 376) | pub(crate) fn default_u16_max() -> u16 {
  type LanguageSnippetExecutionConfig (line 383) | pub struct LanguageSnippetExecutionConfig {
  type SnippetExecutorConfig (line 398) | pub struct SnippetExecutorConfig {
  type ImageProtocol (line 413) | pub enum ImageProtocol {
  method from (line 440) | fn from(protocol: &ImageProtocol) -> Self {
  type KeyBindingsConfig (line 459) | pub struct KeyBindingsConfig {
  method default (line 532) | fn default() -> Self {
  type SpeakerNotesConfig (line 557) | pub struct SpeakerNotesConfig {
  method default (line 572) | fn default() -> Self {
  type ExportConfig (line 585) | pub struct ExportConfig {
  type PauseExportPolicy (line 606) | pub enum PauseExportPolicy {
  type SnippetsExportPolicy (line 619) | pub enum SnippetsExportPolicy {
  type ExportDimensionsConfig (line 632) | pub struct ExportDimensionsConfig {
  type PdfExportConfig (line 644) | pub struct PdfExportConfig {
  type ExportFontsConfig (line 653) | pub struct ExportFontsConfig {
  type SlideTransitionConfig (line 671) | pub struct SlideTransitionConfig {
  type SlideTransitionStyleConfig (line 688) | pub enum SlideTransitionStyleConfig {
  function make_keybindings (line 699) | fn make_keybindings<const N: usize>(raw_bindings: [&str; N]) -> Vec<KeyB...
  function default_next_bindings (line 707) | fn default_next_bindings() -> Vec<KeyBinding> {
  function default_next_fast_bindings (line 711) | fn default_next_fast_bindings() -> Vec<KeyBinding> {
  function default_previous_bindings (line 715) | fn default_previous_bindings() -> Vec<KeyBinding> {
  function default_previous_fast_bindings (line 719) | fn default_previous_fast_bindings() -> Vec<KeyBinding> {
  function default_first_slide_bindings (line 723) | fn default_first_slide_bindings() -> Vec<KeyBinding> {
  function default_last_slide_bindings (line 727) | fn default_last_slide_bindings() -> Vec<KeyBinding> {
  function default_go_to_slide_bindings (line 731) | fn default_go_to_slide_bindings() -> Vec<KeyBinding> {
  function default_execute_code_bindings (line 735) | fn default_execute_code_bindings() -> Vec<KeyBinding> {
  function default_reload_bindings (line 739) | fn default_reload_bindings() -> Vec<KeyBinding> {
  function default_toggle_index_bindings (line 743) | fn default_toggle_index_bindings() -> Vec<KeyBinding> {
  function default_toggle_bindings_modal_bindings (line 747) | fn default_toggle_bindings_modal_bindings() -> Vec<KeyBinding> {
  function default_toggle_layout_grid (line 751) | fn default_toggle_layout_grid() -> Vec<KeyBinding> {
  function default_close_modal_bindings (line 755) | fn default_close_modal_bindings() -> Vec<KeyBinding> {
  function default_exit_bindings (line 759) | fn default_exit_bindings() -> Vec<KeyBinding> {
  function default_suspend_bindings (line 763) | fn default_suspend_bindings() -> Vec<KeyBinding> {
  function default_skip_pauses (line 767) | fn default_skip_pauses() -> Vec<KeyBinding> {
  function default_transition_duration_millis (line 771) | fn default_transition_duration_millis() -> u16 {
  function default_transition_frames (line 775) | fn default_transition_frames() -> usize {
  function default_speaker_notes_listen_address (line 780) | pub(crate) fn default_speaker_notes_listen_address() -> SocketAddr {
  function default_speaker_notes_listen_address (line 785) | pub(crate) fn default_speaker_notes_listen_address() -> SocketAddr {
  function default_speaker_notes_publish_address (line 790) | pub(crate) fn default_speaker_notes_publish_address() -> SocketAddr {
  function default_speaker_notes_publish_address (line 795) | pub(crate) fn default_speaker_notes_publish_address() -> SocketAddr {
  function default_bindings (line 805) | fn default_bindings() {
  function default_options_serde (line 811) | fn default_options_serde() {

FILE: src/demo.rs
  constant PRESENTATION (line 19) | const PRESENTATION: &str = r#"
  type ThemesDemo (line 44) | pub struct ThemesDemo {
    method new (line 51) | pub fn new(themes: Themes, bindings: CommandKeyBindings) -> io::Result...
    method run (line 57) | pub fn run(mut self) -> Result<(), Box<dyn std::error::Error>> {
    method next_command (line 82) | fn next_command(&mut self) -> io::Result<DemoCommand> {
    method build (line 99) | fn build(
  type DemoCommand (line 133) | enum DemoCommand {
  function demo_presentation (line 146) | fn demo_presentation() {

FILE: src/export/exporter.rs
  type OutputDirectory (line 37) | pub enum OutputDirectory {
    method temporary (line 43) | pub fn temporary() -> io::Result<Self> {
    method external (line 48) | pub fn external(path: PathBuf) -> io::Result<Self> {
    method path (line 53) | pub(crate) fn path(&self) -> &Path {
  type Exporter (line 62) | pub struct Exporter<'a> {
  function new (line 78) | pub fn new(
  function build_renderer (line 117) | fn build_renderer(
  function export_pdf (line 155) | pub fn export_pdf(
  function export_html (line 190) | pub fn export_html(
  function wait_async_renders_parallel (line 219) | fn wait_async_renders_parallel(presentation: &mut Presentation) {
  function wait_async_renders_sequential (line 250) | fn wait_async_renders_sequential(presentation: &mut Presentation) {
  function validate_weasyprint_exists (line 271) | fn validate_weasyprint_exists() -> Result<(), ExportError> {
  function validate_theme_colors (line 280) | fn validate_theme_colors(presentation: &Presentation) -> Result<(), Expo...
  function log (line 300) | fn log(text: &str) -> io::Result<()> {
  type ExportError (line 313) | pub enum ExportError {
  type RenderMany (line 340) | struct RenderMany(Vec<RenderOperation>);
  method as_render_operations (line 343) | fn as_render_operations(&self, _: &WindowSize) -> Vec<RenderOperation> {

FILE: src/export/html.rs
  type HtmlText (line 4) | pub(crate) enum HtmlText {
    method new (line 10) | pub(crate) fn new(text: &str, style: &TextStyle, font_size: FontSize) ...
    method fmt (line 48) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type FontSize (line 56) | pub(crate) enum FontSize {
    method scale (line 61) | fn scale(&self, size: u8) -> String {
  function color_to_html (line 68) | pub(crate) fn color_to_html(color: &Color) -> String {
  function html_text (line 109) | fn html_text(#[case] style: TextStyle, #[case] expected_style: &str) {
  function render_span (line 119) | fn render_span() {

FILE: src/export/output.rs
  constant FONT_NAME (line 22) | const FONT_NAME: &str = "presenterm-font";
  constant FONT_SIZE_WIDTH (line 28) | const FONT_SIZE_WIDTH: f64 = 0.605;
  constant FONT_SIZE (line 30) | const FONT_SIZE: u16 = 10;
  constant LINE_HEIGHT (line 31) | const LINE_HEIGHT: u16 = 12;
  type HtmlSlide (line 33) | struct HtmlSlide {
    method new (line 39) | fn new(grid: TerminalGrid) -> Result<Self, ExportError> {
    method finalize_string (line 81) | fn finalize_string(s: &str, style: &TextStyle) -> String {
  type ContentManager (line 86) | pub(crate) struct ContentManager {
    method new (line 91) | pub(crate) fn new(output_directory: OutputDirectory) -> Self {
    method persist_file (line 95) | fn persist_file(&self, name: &str, data: &[u8]) -> io::Result<PathBuf> {
  type OutputFormat (line 102) | pub(crate) enum OutputFormat {
  type ExportRenderer (line 107) | pub(crate) struct ExportRenderer {
    method new (line 116) | pub(crate) fn new(dimensions: WindowSize, output_directory: OutputDire...
    method process_slide (line 127) | pub(crate) fn process_slide(&mut self, slide: Slide) -> Result<(), Exp...
    method generate (line 144) | pub(crate) fn generate(self, output_path: &Path, fonts: &Option<Export...
    method font_configs (line 269) | fn font_configs(config: &ExportFontsConfig) -> FontConfig {
    method make_font_face (line 284) | fn make_font_face(path: &Path, weight: &str, style: &str) -> String {
  type FontConfig (line 299) | struct FontConfig {

FILE: src/export/script.js
  function showCurrentPage (line 7) | function showCurrentPage() {
  function scaler (line 16) | function scaler() {
  function handleKeyPress (line 25) | function handleKeyPress(event) {

FILE: src/main.rs
  constant DEFAULT_THEME (line 58) | const DEFAULT_THEME: &str = "dark";
  constant DEFAULT_THEME_DYNAMIC_DETECTION_TIMEOUT (line 59) | const DEFAULT_THEME_DYNAMIC_DETECTION_TIMEOUT: u64 = 100;
  constant DEFAULT_EXPORT_PIXELS_PER_COLUMN (line 60) | const DEFAULT_EXPORT_PIXELS_PER_COLUMN: u16 = 20;
  constant DEFAULT_EXPORT_PIXELS_PER_ROW (line 61) | const DEFAULT_EXPORT_PIXELS_PER_ROW: u16 = DEFAULT_EXPORT_PIXELS_PER_COL...
  type Cli (line 67) | struct Cli {
  function create_splash (line 150) | fn create_splash() -> String {
  type Customizations (line 165) | struct Customizations {
    method load (line 173) | fn load(config_file_path: Option<PathBuf>, cwd: &Path) -> Result<Self,...
    method load_themes (line 196) | fn load_themes(themes_path: &Path) -> Result<Themes, Box<dyn std::erro...
  type CoreComponents (line 208) | struct CoreComponents {
    method new (line 222) | fn new(cli: &Cli, path: &Path) -> Result<Self, Box<dyn std::error::Err...
    method make_builder_options (line 278) | fn make_builder_options(
    method select_graphics_mode (line 312) | fn select_graphics_mode(cli: &Cli, config: &Config) -> GraphicsMode {
    method theme_name (line 320) | fn theme_name(config: &Config, cli: &Cli) -> String {
    method load_default_theme (line 345) | fn load_default_theme(config: &Config, themes: &Themes, cli: &Cli) -> ...
  type SpeakerNotesComponents (line 356) | struct SpeakerNotesComponents {
    method new (line 362) | fn new(cli: &Cli, config: &Config, path: &Path) -> anyhow::Result<Self> {
  function overflow_validation_enabled (line 381) | fn overflow_validation_enabled(mode: &PresentMode, config: &ValidateOver...
  function run (line 391) | fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
  function main (line 520) | fn main() {

FILE: src/markdown/elements.rs
  type MarkdownElement (line 12) | pub(crate) enum MarkdownElement {
  type SourcePosition (line 74) | pub struct SourcePosition {
    method fmt (line 79) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method from (line 85) | fn from(position: comrak::nodes::Sourcepos) -> Self {
  type LineColumn (line 91) | pub(crate) struct LineColumn {
    method from (line 97) | fn from(position: comrak::nodes::LineColumn) -> Self {
  type Line (line 106) | pub(crate) struct Line<C = Color>(pub(crate) Vec<Text<C>>);
  method default (line 109) | fn default() -> Self {
  function width (line 116) | pub(crate) fn width(&self) -> usize {
  function apply_style (line 123) | pub(crate) fn apply_style(&mut self, style: &TextStyle) {
  function resolve (line 132) | pub(crate) fn resolve(self, palette: &ColorPalette) -> Result<Line<Color...
  function from (line 143) | fn from(text: T) -> Self {
  type Text (line 152) | pub(crate) struct Text<C = Color> {
  method default (line 158) | fn default() -> Self {
  function new (line 165) | pub(crate) fn new<S: Into<String>>(content: S, style: TextStyle<C>) -> S...
  function width (line 170) | pub(crate) fn width(&self) -> usize {
  function from (line 176) | fn from(text: String) -> Self {
  function from (line 182) | fn from(text: &str) -> Self {
  type ListItem (line 189) | pub(crate) struct ListItem {
  type ListItemType (line 204) | pub(crate) enum ListItemType {
  type Table (line 217) | pub(crate) struct Table {
    method columns (line 227) | pub(crate) fn columns(&self) -> usize {
    method iter_column (line 234) | pub(crate) fn iter_column(&self, column: usize) -> impl Iterator<Item ...
  type TableRow (line 243) | pub(crate) struct TableRow(pub(crate) Vec<Line<RawColor>>);
  type Percent (line 247) | pub(crate) struct Percent(pub(crate) u8);
    method as_ratio (line 250) | pub(crate) fn as_ratio(&self) -> f64 {
  type Err (line 256) | type Err = PercentParseError;
  method from_str (line 258) | fn from_str(input: &str) -> Result<Self, Self::Err> {
  type PercentParseError (line 272) | pub enum PercentParseError {

FILE: src/markdown/html.rs
  type HtmlParseOptions (line 6) | pub(crate) struct HtmlParseOptions {
  method default (line 11) | fn default() -> Self {
  type HtmlParser (line 17) | pub(crate) struct HtmlParser {
    method parse (line 22) | pub(crate) fn parse(self, input: &str) -> Result<HtmlInline, ParseHtml...
    method parse_attributes (line 45) | fn parse_attributes(&self, attributes: &Attributes) -> Result<TextStyl...
    method parse_css_attribute (line 65) | fn parse_css_attribute(&self, attribute: &str, style: &mut TextStyle<R...
    method parse_color (line 87) | fn parse_color(input: &str) -> Result<RawColor, ParseHtmlError> {
  type HtmlInline (line 103) | pub(crate) enum HtmlInline {
  type HtmlTag (line 109) | pub(crate) enum HtmlTag {
  type ParseHtmlError (line 115) | pub(crate) enum ParseHtmlError {
    method from (line 145) | fn from(e: ParseColorError) -> Self {
  function parse_style (line 156) | fn parse_style() {
  function parse_sup (line 164) | fn parse_sup() {
  function parse_class (line 171) | fn parse_class() {
  function parse_end_tag (line 185) | fn parse_end_tag(#[case] input: &str, #[case] tag: HtmlTag) {
  function parse_invalid_html (line 196) | fn parse_invalid_html(#[case] input: &str) {
  function parse_color (line 203) | fn parse_color(#[case] input: &str, #[case] expected: Color) {
  function parse_invalid_color (line 211) | fn parse_invalid_color(#[case] input: &str) {

FILE: src/markdown/parse.rs
  type ParseResult (line 24) | pub(crate) type ParseResult<T> = Result<T, ParseError>;
  type ParserOptions (line 26) | struct ParserOptions(comrak::Options<'static>);
  method default (line 29) | fn default() -> Self {
  type MarkdownParser (line 47) | pub struct MarkdownParser<'a> {
  function new (line 54) | pub fn new(arena: &'a Arena<'a>) -> Self {
  function parse (line 59) | pub(crate) fn parse(&self, contents: &str) -> ParseResult<Vec<MarkdownEl...
  function parse_inlines (line 70) | pub(crate) fn parse_inlines(&self, line: &str) -> Result<Line<RawColor>,...
  function parse_node (line 98) | fn parse_node(&self, node: &'a AstNode<'a>) -> ParseResult<Vec<MarkdownE...
  function parse_front_matter (line 121) | fn parse_front_matter(contents: &str) -> ParseResult<MarkdownElement> {
  function parse_html_block (line 133) | fn parse_html_block(&self, block: &NodeHtmlBlock, sourcepos: Sourcepos) ...
  function parse_block_quote (line 145) | fn parse_block_quote(&self, node: &'a AstNode<'a>) -> ParseResult<Markdo...
  function parse_code_block (line 161) | fn parse_code_block(block: &NodeCodeBlock, sourcepos: Sourcepos) -> Pars...
  function parse_alert (line 172) | fn parse_alert(&self, alert: &NodeAlert, node: &'a AstNode<'a>) -> Parse...
  function parse_footnote_definition (line 177) | fn parse_footnote_definition(
  function parse_heading (line 193) | fn parse_heading(&self, heading: &NodeHeading, node: &'a AstNode<'a>) ->...
  function parse_paragraph (line 203) | fn parse_paragraph(&self, node: &'a AstNode<'a>) -> ParseResult<Vec<Mark...
  function parse_exheading (line 229) | fn parse_exheading(&self, node: &'a AstNode<'a>) -> ParseResult<Vec<Line...
  function parse_text (line 250) | fn parse_text(&self, node: &'a AstNode<'a>) -> ParseResult<Line<RawColor...
  function parse_list (line 265) | fn parse_list(&self, root: &'a AstNode<'a>, depth: u8) -> ParseResult<Ve...
  function parse_list_item (line 285) | fn parse_list_item(&self, item: &NodeList, root: &'a AstNode<'a>, depth:...
  function parse_table (line 314) | fn parse_table(&self, node: &'a AstNode<'a>) -> ParseResult<MarkdownElem...
  function parse_table_row (line 336) | fn parse_table_row(&self, node: &'a AstNode<'a>) -> ParseResult<TableRow> {
  type SoftBreak (line 354) | enum SoftBreak {
  type StringifyImages (line 359) | enum StringifyImages {
  type InlinesParser (line 364) | struct InlinesParser<'a> {
  function new (line 373) | fn new(arena: &'a Arena<'a>, soft_break: SoftBreak, stringify_images: St...
  function parse (line 377) | fn parse(mut self, node: &'a AstNode<'a>) -> ParseResult<Vec<Inline>> {
  function store_pending_text (line 383) | fn store_pending_text(&mut self) {
  function process_node (line 390) | fn process_node(
  function process_children (line 510) | fn process_children(&mut self, root: &'a AstNode<'a>, base_style: TextSt...
  type HtmlStyle (line 537) | enum HtmlStyle {
  type Inline (line 542) | enum Inline {
    method kind (line 549) | fn kind(&self) -> &'static str {
  type ParseError (line 560) | pub struct ParseError {
    method new (line 575) | fn new<S: Into<SourcePosition>>(kind: ParseErrorKind, sourcepos: S) ->...
  method fmt (line 569) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ParseErrorKind (line 582) | pub(crate) enum ParseErrorKind {
    method with_sourcepos (line 626) | fn with_sourcepos<S: Into<SourcePosition>>(self, sourcepos: S) -> Pars...
  method fmt (line 609) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Identifier (line 631) | trait Identifier {
    method identifier (line 632) | fn identifier(&self) -> &'static str;
    method identifier (line 636) | fn identifier(&self) -> &'static str {
  type ParseInlinesError (line 687) | pub(crate) struct ParseInlinesError(String);
  function try_parse (line 696) | fn try_parse(input: &str) -> Result<Vec<MarkdownElement>, ParseError> {
  function parse_single (line 701) | fn parse_single(input: &str) -> MarkdownElement {
  function parse_all (line 707) | fn parse_all(input: &str) -> Vec<MarkdownElement> {
  function slide_metadata (line 712) | fn slide_metadata() {
  function paragraph (line 725) | fn paragraph() {
  function html_inlines (line 750) | fn html_inlines() {
  function invalid_html_inlines (line 772) | fn invalid_html_inlines(#[case] input: &str, #[case] expected_error: Par...
  function link_wo_label_wo_title (line 778) | fn link_wo_label_wo_title() {
  function link_w_label_wo_title (line 789) | fn link_w_label_wo_title() {
  function link_wo_label_w_title (line 805) | fn link_wo_label_w_title() {
  function link_w_label_w_title (line 821) | fn link_w_label_w_title() {
  function wikilink_wo_title (line 840) | fn wikilink_wo_title() {
  function image (line 850) | fn image() {
  function image_within_text (line 857) | fn image_within_text() {
  function external_image (line 867) | fn external_image() {
  function setex_heading (line 875) | fn setex_heading() {
  function heading (line 888) | fn heading() {
  function unordered_list (line 898) | fn unordered_list() {
  function ordered_list_starting_non_one (line 918) | fn ordered_list_starting_non_one() {
  function line_breaks (line 938) | fn line_breaks() {
  function code_block (line 959) | fn code_block() {
  function inline_code (line 973) | fn inline_code() {
  function table (line 984) | fn table() {
  function comment (line 1001) | fn comment() {
  function list_comment_in_between (line 1012) | fn list_comment_in_between() {
  function block_quote (line 1026) | fn block_quote() {
  function multiline_block_quote (line 1064) | fn multiline_block_quote() {
  function thematic_break (line 1085) | fn thematic_break() {
  function error_lines_offset_by_front_matter (line 1100) | fn error_lines_offset_by_front_matter() {
  function comment_lines_offset_by_front_matter (line 1118) | fn comment_lines_offset_by_front_matter() {
  function front_matter_newlines (line 1136) | fn front_matter_newlines(#[case] nl: &str) {
  function parse_alert (line 1146) | fn parse_alert() {
  function parse_inlines (line 1159) | fn parse_inlines() {
  function footnote (line 1174) | fn footnote() {

FILE: src/markdown/text.rs
  type WeightedLine (line 12) | pub(crate) struct WeightedLine {
    method split (line 20) | pub(crate) fn split(&self, max_length: usize) -> SplitTextIter<'_> {
    method width (line 25) | pub(crate) fn width(&self) -> usize {
    method font_size (line 30) | pub(crate) fn font_size(&self) -> u8 {
    method from (line 36) | fn from(block: Line) -> Self {
    method from (line 42) | fn from(mut texts: Vec<Text>) -> Self {
    method from (line 67) | fn from(text: String) -> Self {
    method from (line 75) | fn from(text: &str) -> Self {
  type CharAccumulator (line 81) | struct CharAccumulator {
  type WeightedText (line 88) | pub(crate) struct WeightedText {
    method to_ref (line 94) | fn to_ref(&self) -> WeightedTextRef<'_> {
    method width (line 98) | pub(crate) fn width(&self) -> usize {
    method text (line 102) | pub(crate) fn text(&self) -> &Text {
    method from (line 108) | fn from(text: S) -> Self {
    method from (line 114) | fn from(text: Text) -> Self {
    method fmt (line 129) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type SplitTextIter (line 135) | pub(crate) struct SplitTextIter<'a> {
  function new (line 142) | fn new(texts: &'a [WeightedText], max_length: usize) -> Self {
  type Item (line 148) | type Item = Vec<WeightedTextRef<'a>>;
  method next (line 150) | fn next(&mut self) -> Option<Self::Item> {
  type WeightedTextRef (line 183) | pub(crate) struct WeightedTextRef<'a> {
  function into_parts (line 191) | pub(crate) fn into_parts(self) -> (&'a str, TextStyle) {
  function word_split_at_length (line 199) | fn word_split_at_length(&self, max_length: usize) -> (Self, Self) {
  function substr (line 213) | fn substr(&self, max_length: usize) -> &'a str {
  function make_ref (line 218) | fn make_ref(&self, from: usize, to: usize) -> Self {
  function trim_start (line 226) | fn trim_start(self) -> Self {
  function width (line 233) | pub(crate) fn width(&self) -> usize {
  function bytes_until (line 239) | fn bytes_until(&self, index: usize) -> usize {
  function join_lines (line 252) | fn join_lines<'a>(lines: impl Iterator<Item = Vec<WeightedTextRef<'a>>>)...
  function text_creation (line 257) | fn text_creation() {
  function text_creation_utf8 (line 265) | fn text_creation_utf8() {
  function minimal_split (line 290) | fn minimal_split() {
  function no_spaces_split (line 299) | fn no_spaces_split() {
  function font_size_split (line 308) | fn font_size_split() {
  function make_ref (line 317) | fn make_ref() {
  function word_split (line 330) | fn word_split() {
  function split_at_full_length (line 338) | fn split_at_full_length() {
  function no_split_necessary (line 346) | fn no_split_necessary() {
  function split_lines_single (line 358) | fn split_lines_single() {
  function split_lines_multi (line 367) | fn split_lines_multi() {
  function long_splits (line 383) | fn long_splits() {
  function prefixed_by_whitespace (line 399) | fn prefixed_by_whitespace() {
  function utf8_character (line 407) | fn utf8_character() {
  function many_utf8_characters (line 415) | fn many_utf8_characters() {
  function no_whitespaces_ascii (line 424) | fn no_whitespaces_ascii() {
  function no_whitespaces_utf8 (line 433) | fn no_whitespaces_utf8() {
  function wide_characters (line 442) | fn wide_characters() {
  function compaction (line 457) | fn compaction(#[case] texts: &[Text], #[case] expected: usize) {

FILE: src/markdown/text_style.rs
  type TextStyle (line 14) | pub(crate) struct TextStyle<C = Color> {
  method default (line 21) | fn default() -> Self {
  function colored (line 30) | pub(crate) fn colored(colors: Colors<C>) -> Self {
  function size (line 34) | pub(crate) fn size(mut self, size: u8) -> Self {
  function bold (line 40) | pub(crate) fn bold(self) -> Self {
  function italics (line 45) | pub(crate) fn italics(self) -> Self {
  function code (line 50) | pub(crate) fn code(self) -> Self {
  function strikethrough (line 55) | pub(crate) fn strikethrough(self) -> Self {
  function underlined (line 60) | pub(crate) fn underlined(self) -> Self {
  function link_label (line 65) | pub(crate) fn link_label(self) -> Self {
  function link_title (line 70) | pub(crate) fn link_title(self) -> Self {
  function link_url (line 75) | pub(crate) fn link_url(self) -> Self {
  function superscript (line 80) | pub(crate) fn superscript(self) -> Self {
  function bg_color (line 85) | pub(crate) fn bg_color<U: Into<C>>(mut self, color: U) -> Self {
  function fg_color (line 91) | pub(crate) fn fg_color<U: Into<C>>(mut self, color: U) -> Self {
  function colors (line 97) | pub(crate) fn colors(mut self, colors: Colors<C>) -> Self {
  function is_code (line 103) | pub(crate) fn is_code(&self) -> bool {
  function is_bold (line 108) | pub(crate) fn is_bold(&self) -> bool {
  function is_italics (line 113) | pub(crate) fn is_italics(&self) -> bool {
  function merge (line 118) | pub(crate) fn merge(&mut self, other: &TextStyle<C>) {
  function merged (line 126) | pub(crate) fn merged(mut self, other: &TextStyle<C>) -> Self {
  function add_flag (line 131) | fn add_flag(mut self, flag: TextFormatFlags) -> Self {
  function has_flag (line 136) | fn has_flag(&self, flag: TextFormatFlags) -> bool {
  function apply (line 143) | pub(crate) fn apply<'a>(
  function into_raw (line 173) | pub(crate) fn into_raw(self) -> TextStyle<RawColor> {
  function iter_attributes (line 182) | pub(crate) fn iter_attributes(&self) -> AttributeIterator {
  function resolve (line 193) | pub(crate) fn resolve(&self, palette: &ColorPalette) -> Result<TextStyle...
  type AttributeIterator (line 199) | pub(crate) struct AttributeIterator {
  type Item (line 207) | type Item = TextAttribute;
  method next (line 209) | fn next(&mut self) -> Option<Self::Item> {
  type TextAttribute (line 243) | pub(crate) enum TextAttribute {
  type FontSizedStr (line 254) | struct FontSizedStr<'a> {
  function fmt (line 260) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type FontSize (line 273) | enum FontSize {
  type TextFormatFlags (line 279) | enum TextFormatFlags {
  type Color (line 289) | pub(crate) enum Color {
    method new (line 310) | pub(crate) fn new(r: u8, g: u8, b: u8) -> Self {
    method from_8bit (line 314) | pub(crate) fn from_8bit(color: u8) -> Option<Self> {
    method as_rgb (line 346) | pub(crate) fn as_rgb(&self) -> Option<(u8, u8, u8)> {
    method from_ansi (line 353) | pub(crate) fn from_ansi(color: u8) -> Option<Self> {
  function from (line 370) | fn from(value: Color) -> Self {
  type PaletteColorError (line 396) | pub(crate) struct PaletteColorError(String);
  type UndefinedPaletteColorError (line 400) | pub(crate) struct UndefinedPaletteColorError(pub(crate) String);
  type Colors (line 404) | pub(crate) struct Colors<C = Color> {
  method default (line 413) | fn default() -> Self {
  function resolve (line 419) | pub(crate) fn resolve(&self, palette: &ColorPalette) -> Result<Colors<Co...
  function from (line 427) | fn from(value: Colors) -> Self {
  type TryIntoSuperscript (line 434) | trait TryIntoSuperscript {
    method try_into_superscript (line 435) | fn try_into_superscript(&self) -> Option<String>;
    method try_into_superscript (line 439) | fn try_into_superscript(&self) -> Option<String> {
  function iterate_attributes (line 517) | fn iterate_attributes(#[case] style: TextStyle, #[case] expected: &[Text...

FILE: src/presentation/builder/comment.rs
  function process_comment (line 12) | pub(crate) fn process_comment(&mut self, comment: String, source_positio...
  function process_comment_command_presentation_mode (line 36) | fn process_comment_command_presentation_mode(
  function process_comment_command_speaker_notes_mode (line 136) | fn process_comment_command_speaker_notes_mode(&mut self, comment_command...
  function should_ignore_comment (line 152) | fn should_ignore_comment(&self, comment: &str) -> bool {
  function process_include (line 167) | fn process_include(&mut self, path: PathBuf, source_position: SourcePosi...
  type CommentCommand (line 204) | pub(crate) enum CommentCommand {
    method generate_samples (line 231) | pub(crate) fn generate_samples() -> Vec<&'static str> {
  type Err (line 270) | type Err = CommandParseError;
  method from_str (line 272) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type CommentCommandAlignment (line 283) | pub(crate) enum CommentCommandAlignment {
  type CommandParseError (line 290) | pub struct CommandParseError(#[from] serde_yaml::Error);
    method fmt (line 293) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function command_formatting (line 324) | fn command_formatting(#[case] input: &str, #[case] expected: CommentComm...
  function ignore_comments (line 338) | fn ignore_comments(#[case] comment: &str) {
  function comment_prefix (line 347) | fn comment_prefix(#[case] comment: &str, #[case] should_work: bool) {
  function layout_without_init (line 356) | fn layout_without_init() {
  function already_in_column (line 362) | fn already_in_column() {
  function column_index_overflow (line 372) | fn column_index_overflow() {
  function invalid_layouts (line 384) | fn invalid_layouts(#[case] definition: &str) {
  function operation_without_enter_column (line 390) | fn operation_without_enter_column() {
  function end_slide_inside_layout (line 400) | fn end_slide_inside_layout() {
  function end_slide_inside_column (line 410) | fn end_slide_inside_column() {
  function columns (line 421) | fn columns() {
  function columns_back_and_forth (line 460) | fn columns_back_and_forth() {
  function uneven_columns (line 506) | fn uneven_columns() {
  function uneven_three_columns (line 545) | fn uneven_three_columns() {
  function pause_layout (line 577) | fn pause_layout() {
  function pause_new_slide (line 593) | fn pause_new_slide() {
  function pause_layout_new_slide (line 607) | fn pause_layout_new_slide() {
  function skip_slide (line 630) | fn skip_slide() {
  function skip_all_slides (line 645) | fn skip_all_slides() {
  function skip_slide_pauses (line 657) | fn skip_slide_pauses() {
  function skip_slide_speaker_note (line 673) | fn skip_slide_speaker_note() {
  function speaker_notes (line 688) | fn speaker_notes() {
  function speaker_notes_pause (line 701) | fn speaker_notes_pause() {
  function alignment (line 716) | fn alignment() {
  function include (line 742) | fn include() {
  function self_include (line 817) | fn self_include() {
  function include_cycle (line 829) | fn include_cycle() {

FILE: src/presentation/builder/error.rs
  type BuildError (line 22) | pub(crate) enum BuildError {
  type InvalidPresentation (line 77) | pub(crate) enum InvalidPresentation {
  type FileSourcePosition (line 128) | pub(crate) struct FileSourcePosition {
    method fmt (line 134) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type FormatError (line 141) | pub(super) trait FormatError {
    method format_error (line 142) | fn format_error(self) -> String;
    method format_error (line 146) | fn format_error(self) -> String {
  type ErrorContextBuilder (line 152) | pub(super) struct ErrorContextBuilder<'a> {
  function new (line 162) | pub(super) fn new(source_line: &'a str, error: &'a str) -> Self {
  function position (line 173) | pub(super) fn position(mut self, position: SourcePosition) -> Self {
  function column (line 179) | pub(super) fn column(mut self, column: usize) -> Self {
  function build (line 184) | pub(super) fn build(self) -> String {
  type ErrorContextBuilderExt (line 221) | trait ErrorContextBuilderExt {
    method into_lines (line 222) | fn into_lines(self) -> Vec<String>;
    method into_lines (line 226) | fn into_lines(self) -> Vec<String> {
  function make_builder (line 232) | fn make_builder<'a>(source_line: &'a str, error: &'a str) -> ErrorContex...
  function position (line 240) | fn position() {
  function no_position (line 254) | fn no_position() {
  function column (line 266) | fn column() {

FILE: src/presentation/builder/frontmatter.rs
  function process_front_matter (line 21) | pub(crate) fn process_front_matter(&mut self, contents: &str) -> BuildRe...
  function set_theme (line 55) | fn set_theme(&mut self, metadata: &PresentationThemeMetadata) -> BuildRe...
  function push_intro_slide (line 109) | fn push_intro_slide(&mut self, metadata: PresentationMetadata) -> BuildR...
  function push_intro_slide_text (line 179) | fn push_intro_slide_text(&mut self, text: Text, element_type: ElementTyp...
  function format_multiline (line 184) | fn format_multiline(
  type StrictPresentationMetadata (line 212) | struct StrictPresentationMetadata {
  method from (line 242) | fn from(strict: StrictPresentationMetadata) -> Self {
  function multiline_centered_title (line 254) | fn multiline_centered_title() {

FILE: src/presentation/builder/heading.rs
  function push_slide_title (line 9) | pub(crate) fn push_slide_title(&mut self, text: Vec<Line<RawColor>>) -> ...
  function push_heading (line 48) | pub(crate) fn push_heading(&mut self, level: u8, text: Line<RawColor>) -...
  function slide_title (line 89) | fn slide_title() {
  function slide_title_prefix (line 113) | fn slide_title_prefix() {
  function h1_slide_title (line 131) | fn h1_slide_title() {
  function h1_slide_title_implicit_slides (line 151) | fn h1_slide_title_implicit_slides() {
  function centered_slide_title (line 176) | fn centered_slide_title() {
  function implicit_slide_ends (line 195) | fn implicit_slide_ends() {
  function headings (line 215) | fn headings() {
  function heading_font_size (line 242) | fn heading_font_size() {

FILE: src/presentation/builder/images.rs
  function push_image_from_path (line 13) | pub(crate) fn push_image_from_path(
  function push_image (line 26) | pub(crate) fn push_image(&mut self, image: Image, title: String, source_...
  function parse_image_attributes (line 41) | fn parse_image_attributes(
  function parse_image_attribute (line 59) | fn parse_image_attribute(input: &str, attributes: &mut ImageAttributes) ...
  type ImageAttributeError (line 75) | pub(crate) enum ImageAttributeError {
  type ImageAttributes (line 87) | struct ImageAttributes {
  function image_attributes (line 102) | fn image_attributes(#[case] input: &str, #[case] expectation: Option<u8>) {
  function image_attributes_empty_prefix (line 112) | fn image_attributes_empty_prefix(#[case] input: &str, #[case] expectatio...

FILE: src/presentation/builder/list.rs
  function push_list (line 12) | pub(crate) fn push_list(&mut self, list: Vec<ListItem>) -> BuildResult {
  function push_list_item (line 48) | fn push_list_item(&mut self, index: usize, item: ListItem, block_length:...
  function list_item_prefix (line 74) | fn list_item_prefix(&self, item: &ListItem) -> Text {
  type ListIterator (line 111) | struct ListIterator<I> {
  function new (line 119) | fn new<T>(remaining: T, next_index: usize) -> Self
  type Item (line 132) | type Item = IndexedListItem;
  method next (line 134) | fn next(&mut self) -> Option<Self::Item> {
  type IndexedListItem (line 157) | struct IndexedListItem {
  function iterate_list (line 170) | fn iterate_list() {
  function iterate_list_starting_from_other (line 189) | fn iterate_list_starting_from_other() {
  function unordered (line 203) | fn unordered() {
  function unordered_paused (line 226) | fn unordered_paused() {
  function ordered_period (line 240) | fn ordered_period() {
  function ordered_parens (line 263) | fn ordered_parens() {
  function ordered_paused (line 275) | fn ordered_paused() {
  function visible_pauses (line 292) | fn visible_pauses(#[case] advances: usize) {
  function incremental_lists (line 321) | fn incremental_lists(
  function font_size (line 360) | fn font_size() {
  function newlines (line 372) | fn newlines() {
  function incremental_lists_end_of_slide (line 384) | fn incremental_lists_end_of_slide() {
  function pause_after_list (line 401) | fn pause_after_list() {

FILE: src/presentation/builder/mod.rs
  type BuildResult (line 66) | pub(crate) type BuildResult = Result<(), BuildError>;
  type Themes (line 69) | pub struct Themes {
  type PresentationBuilderOptions (line 75) | pub struct PresentationBuilderOptions {
    method merge (line 103) | fn merge(&mut self, options: OptionsConfig) {
  method default (line 127) | fn default() -> Self {
  type PresentationBuilder (line 161) | pub(crate) struct PresentationBuilder<'a, 'b> {
  function new (line 189) | pub(crate) fn new(
  function build (line 228) | pub(crate) fn build(self, path: &Path) -> Result<Presentation, BuildErro...
  function build_from_parsed (line 233) | pub(crate) fn build_from_parsed(mut self, elements: Vec<MarkdownElement>...
  function build_with_reader (line 294) | fn build_with_reader<F: PresentationReader>(self, path: &Path, reader: F...
  function build_modal_background (line 305) | fn build_modal_background(&self) -> Result<Image, RegisterImageError> {
  function validate_last_operation (line 319) | fn validate_last_operation(&mut self) -> BuildResult {
  function set_colors (line 345) | fn set_colors(&mut self, colors: Colors) {
  function push_slide_prelude (line 349) | fn push_slide_prelude(&mut self) {
  function process_element_for_presentation_mode (line 365) | fn process_element_for_presentation_mode(&mut self, element: MarkdownEle...
  function process_element_for_speaker_notes_mode (line 396) | fn process_element_for_speaker_notes_mode(&mut self, element: MarkdownEl...
  function set_code_theme (line 414) | fn set_code_theme(&mut self) -> BuildResult {
  function invalid_presentation (line 422) | fn invalid_presentation<E>(&self, source_position: SourcePosition, error...
  function resource_base_path (line 437) | fn resource_base_path(&self) -> ResourceBasePath {
  function validate_column_layout (line 441) | fn validate_column_layout(&self, columns: &[u8], source_position: Source...
  function push_pause (line 455) | fn push_pause(&mut self) {
  function push_paragraph (line 471) | fn push_paragraph(&mut self, lines: Vec<Line<RawColor>>) -> BuildResult {
  function process_thematic_break (line 480) | fn process_thematic_break(&mut self) {
  function push_text (line 492) | fn push_text(&mut self, line: Line, element_type: ElementType) {
  function push_aligned_text (line 497) | fn push_aligned_text(&mut self, mut block: Line, alignment: Alignment) {
  function push_line_break (line 510) | fn push_line_break(&mut self) {
  function push_line_breaks (line 514) | fn push_line_breaks(&mut self, count: usize) {
  function terminate_slide (line 518) | fn terminate_slide(&mut self) {
  function apply_theme_text_style (line 542) | fn apply_theme_text_style(&self, text: &mut Text) {
  function is_chunk_empty (line 554) | fn is_chunk_empty(operations: &[RenderOperation]) -> bool {
  function generate_footer (line 566) | fn generate_footer(&self) -> Result<Vec<RenderOperation>, BuildError> {
  function slide_font_size (line 577) | fn slide_font_size(&self) -> u8 {
  type PresentationReader (line 583) | trait PresentationReader {
    method read (line 584) | fn read(&self, path: &Path) -> io::Result<String>;
    method read (line 590) | fn read(&self, path: &Path) -> io::Result<String> {
    method read (line 650) | fn read(&self, _path: &Path) -> io::Result<String> {
  type FilesystemPresentationReader (line 587) | struct FilesystemPresentationReader;
  type SlideState (line 596) | struct SlideState {
  type LayoutState (line 614) | enum LayoutState {
  type LastElement (line 627) | enum LastElement {
  type MemoryPresentationReader (line 645) | struct MemoryPresentationReader {
  type Input (line 655) | pub(crate) enum Input {
    method from (line 661) | fn from(value: &'_ str) -> Self {
    method from (line 667) | fn from(value: String) -> Self {
    method from (line 673) | fn from(value: Vec<MarkdownElement>) -> Self {
  type Test (line 678) | pub(crate) struct Test {
    method new (line 686) | pub(crate) fn new<T: Into<Input>>(input: T) -> Self {
    method options (line 696) | pub(crate) fn options(mut self, options: PresentationBuilderOptions) -...
    method resources_path (line 701) | pub(crate) fn resources_path<P: Into<PathBuf>>(mut self, path: P) -> S...
    method theme (line 706) | pub(crate) fn theme(mut self, theme: raw::PresentationTheme) -> Self {
    method disable_exec_replace (line 711) | pub(crate) fn disable_exec_replace(mut self) -> Self {
    method disable_exec (line 716) | pub(crate) fn disable_exec(mut self) -> Self {
    method with_builder (line 721) | pub(crate) fn with_builder<T, F>(&self, callback: F) -> T
    method render (line 748) | pub(crate) fn render(self) -> PresentationRender {
    method build (line 753) | pub(crate) fn build(self) -> Presentation {
    method expect_invalid (line 757) | pub(crate) fn expect_invalid(self) -> BuildError {
    method try_build (line 761) | pub(crate) fn try_build(self) -> Result<Presentation, BuildError> {
  type PresentationRender (line 773) | pub(crate) struct PresentationRender {
    method new (line 783) | fn new(presentation: Presentation) -> Self {
    method rows (line 794) | pub(crate) fn rows(mut self, rows: u16) -> Self {
    method columns (line 799) | pub(crate) fn columns(mut self, columns: u16) -> Self {
    method advances (line 804) | pub(crate) fn advances(mut self, number: usize) -> Self {
    method run_async_renders (line 809) | pub(crate) fn run_async_renders(mut self, policy: RunAsyncRendersPolic...
    method map_background (line 814) | pub(crate) fn map_background(mut self, color: Color, c: char) -> Self {
    method into_lines (line 819) | pub(crate) fn into_lines(self) -> Vec<String> {
    method into_parts (line 823) | pub(crate) fn into_parts(self) -> (Vec<String>, Vec<String>) {
  type RunAsyncRendersPolicy (line 883) | pub(crate) enum RunAsyncRendersPolicy {

FILE: src/presentation/builder/quote.rs
  function push_block_quote (line 14) | pub(crate) fn push_block_quote(&mut self, lines: Vec<Line<RawColor>>) ->...
  function push_alert (line 26) | pub(crate) fn push_alert(
  function push_quoted_text (line 54) | fn push_quoted_text(
  function quote (line 102) | fn quote(#[case] alignment: raw::Alignment, #[case] line: &str, #[case] ...
  function alert (line 128) | fn alert() {

FILE: src/presentation/builder/snippet.rs
  function push_code (line 31) | pub(crate) fn push_code(&mut self, info: String, code: String, source_po...
  function push_detached_code_execution (line 147) | pub(crate) fn push_detached_code_execution(&mut self, handle: WrappedSni...
  function is_execution_allowed (line 157) | fn is_execution_allowed(&self, args: &SnippetExecArgs) -> bool {
  function push_code_lines (line 164) | fn push_code_lines(&mut self, snippet: &Snippet) -> u16 {
  function push_replace_code_execution (line 180) | fn push_replace_code_execution(&mut self, snippet: Snippet, executor: La...
  function push_replace_pty_code_execution (line 194) | fn push_replace_pty_code_execution(
  function load_external_snippet (line 212) | fn load_external_snippet(
  function filter_lines (line 232) | fn filter_lines(code: String, start: Option<usize>, end: Option<usize>) ...
  function push_rendered_code (line 242) | fn push_rendered_code(&mut self, code: Snippet, source_position: SourceP...
  function highlight_lines (line 261) | fn highlight_lines(
  function code_style (line 302) | fn code_style(&self, snippet: &Snippet) -> CodeBlockStyle {
  function push_execution_disabled_operation (line 310) | fn push_execution_disabled_operation(&mut self, exec_type: ExecutionType) {
  function push_code_as_image (line 324) | fn push_code_as_image(&mut self, snippet: Snippet, executor: LanguageSni...
  function push_acquire_terminal_execution (line 332) | fn push_acquire_terminal_execution(
  function push_indicator (line 351) | fn push_indicator<T: Into<WrappedSnippetHandle>>(&mut self, handle: T, b...
  function push_code_execution (line 362) | fn push_code_execution(&mut self, block_length: u16, handle: SnippetHand...
  function push_pty_code_execution (line 383) | fn push_pty_code_execution(&mut self, handle: PtySnippetHandle) -> Build...
  function push_differ (line 395) | fn push_differ(&mut self, text: String) {
  function push_validator (line 399) | fn push_validator(&mut self, snippet: &Snippet, executor: &LanguageSnipp...
  type Differ (line 409) | struct Differ(String);
  method as_render_operations (line 412) | fn as_render_operations(&self, _: &WindowSize) -> Vec<RenderOperation> {
  method diffable_content (line 416) | fn diffable_content(&self) -> Option<&str> {
  function filter_lines (line 444) | fn filter_lines(#[case] start: Option<usize>, #[case] end: Option<usize>...
  function plain (line 452) | fn plain() {
  function external_snippet (line 463) | fn external_snippet() {
  function line_numbers (line 483) | fn line_numbers() {
  function line_numbers_via_theme (line 495) | fn line_numbers_via_theme() {
  function surroundings (line 513) | fn surroundings() {
  function padding (line 535) | fn padding() {
  function exec_no_run (line 560) | fn exec_no_run() {
  function exec_auto (line 578) | fn exec_auto() {
  function validate (line 602) | fn validate() {
  function exec_disabled (line 614) | fn exec_disabled() {
  function exec_replace_disabled (line 632) | fn exec_replace_disabled() {
  function exec (line 650) | fn exec() {
  function exec_font_size (line 698) | fn exec_font_size() {
  function exec_font_size_centered (line 719) | fn exec_font_size_centered() {
  function exec_adjacent_detached_output (line 776) | fn exec_adjacent_detached_output() {
  function exec_detached_output (line 796) | fn exec_detached_output() {
  function exec_replace (line 820) | fn exec_replace() {
  function snippet_exec_replace_centered (line 831) | fn snippet_exec_replace_centered() {
  function exec_replace_font_size (line 849) | fn exec_replace_font_size() {
  function exec_replace_long (line 861) | fn exec_replace_long() {

FILE: src/presentation/builder/sources.rs
  type Inner (line 5) | struct Inner {
  type MarkdownSources (line 10) | pub(crate) struct MarkdownSources {
    method enter (line 15) | pub(crate) fn enter<P: Into<PathBuf>>(&self, path: P) -> Result<Source...
    method current_base_path (line 29) | pub(crate) fn current_base_path(&self) -> PathBuf {
    method resolve_source_position (line 39) | pub(crate) fn resolve_source_position(&self, source_position: SourcePo...
  type SourceGuard (line 46) | pub(crate) struct SourceGuard(Rc<RefCell<Inner>>);
  method drop (line 49) | fn drop(&mut self) {
  type MarkdownSourceError (line 55) | pub(crate) enum MarkdownSourceError {
  function paths (line 69) | fn paths() {

FILE: src/presentation/builder/table.rs
  function push_table (line 9) | pub(crate) fn push_table(&mut self, table: Table) -> BuildResult {
  function prepare_table_row (line 53) | fn prepare_table_row(&self, row: TableRow, widths: &[usize]) -> Result<L...
  function table (line 78) | fn table() {

FILE: src/presentation/builder/tests.rs
  function prelude_appears_once (line 5) | fn prelude_appears_once() {
  function slides_start_with_one_newline (line 28) | fn slides_start_with_one_newline() {
  function extra_fields_in_metadata (line 49) | fn extra_fields_in_metadata() {
  function end_slide_shorthand (line 55) | fn end_slide_shorthand() {
  function parse_front_matter_strict (line 74) | fn parse_front_matter_strict() {
  function footnote (line 82) | fn footnote() {

FILE: src/presentation/diff.rs
  type PresentationDiffer (line 5) | pub(crate) struct PresentationDiffer;
    method find_first_modification (line 9) | pub(crate) fn find_first_modification(original: &Presentation, updated...
  type Modification (line 44) | pub(crate) struct Modification {
  type ContentDiff (line 49) | trait ContentDiff {
    method is_content_different (line 50) | fn is_content_different(&self, other: &Self) -> bool;
    method is_content_different (line 54) | fn is_content_different(&self, other: &Self) -> bool {
    method is_content_different (line 60) | fn is_content_different(&self, other: &Self) -> bool {
    method is_content_different (line 102) | fn is_content_different(&self, other: &Self) -> bool {
  type Dynamic (line 134) | struct Dynamic;
  method as_render_operations (line 137) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  method pollable (line 143) | fn pollable(&self) -> Box<dyn Pollable> {
  function same_not_modified (line 172) | fn same_not_modified(#[case] operation: RenderOperation) {
  function different_text (line 178) | fn different_text() {
  function different_text_alignment (line 185) | fn different_text_alignment() {
  function different_colors (line 198) | fn different_colors() {
  function different_column_layout (line 205) | fn different_column_layout() {
  function different_column (line 220) | fn different_column() {
  function no_slide_changes (line 227) | fn no_slide_changes() {
  function slides_truncated (line 237) | fn slides_truncated() {
  function slides_added (line 251) | fn slides_added() {
  function second_slide_content_changed (line 265) | fn second_slide_content_changed() {
  function presentation_changed_style (line 284) | fn presentation_changed_style() {
  function chunk_change (line 298) | fn chunk_change() {

FILE: src/presentation/mod.rs
  type Modals (line 16) | pub(crate) struct Modals {
  type Presentation (line 23) | pub(crate) struct Presentation {
    method new (line 31) | pub(crate) fn new(slides: Vec<Slide>, modals: Modals, state: Presentat...
    method iter_slides (line 36) | pub(crate) fn iter_slides(&self) -> impl Iterator<Item = &Slide> {
    method iter_slides_mut (line 41) | pub(crate) fn iter_slides_mut(&mut self) -> impl Iterator<Item = &mut ...
    method iter_slide_index_operations (line 46) | pub(crate) fn iter_slide_index_operations(&self) -> impl Iterator<Item...
    method iter_bindings_operations (line 51) | pub(crate) fn iter_bindings_operations(&self) -> impl Iterator<Item = ...
    method into_slides (line 56) | pub(crate) fn into_slides(self) -> Vec<Slide> {
    method current_slide (line 61) | pub(crate) fn current_slide(&self) -> &Slide {
    method current_slide_index (line 66) | pub(crate) fn current_slide_index(&self) -> usize {
    method jump_next (line 71) | pub(crate) fn jump_next(&mut self) -> bool {
    method jump_next_fast (line 80) | pub(crate) fn jump_next_fast(&mut self) -> bool {
    method jump_previous (line 85) | pub(crate) fn jump_previous(&mut self) -> bool {
    method jump_previous_fast (line 94) | pub(crate) fn jump_previous_fast(&mut self) -> bool {
    method jump_first_slide (line 101) | pub(crate) fn jump_first_slide(&mut self) -> bool {
    method jump_last_slide (line 106) | pub(crate) fn jump_last_slide(&mut self) -> bool {
    method go_to_slide (line 112) | pub(crate) fn go_to_slide(&mut self, slide_index: usize) -> bool {
    method jump_chunk (line 124) | pub(crate) fn jump_chunk(&mut self, chunk_index: usize) {
    method current_chunk (line 129) | pub(crate) fn current_chunk(&self) -> usize {
    method current_slide_mut (line 133) | pub(crate) fn current_slide_mut(&mut self) -> &mut Slide {
    method show_all_slide_chunks (line 139) | pub(crate) fn show_all_slide_chunks(&mut self) {
    method jump_next_slide (line 143) | fn jump_next_slide(&mut self) -> bool {
    method jump_previous_slide (line 155) | fn jump_previous_slide(&mut self) -> bool {
    method from (line 169) | fn from(slides: Vec<Slide>) -> Self {
  type AsyncPresentationError (line 176) | pub(crate) struct AsyncPresentationError {
  type AsyncPresentationErrorHolder (line 181) | pub(crate) type AsyncPresentationErrorHolder = Arc<Mutex<Option<AsyncPre...
  type PresentationStateInner (line 184) | pub(crate) struct PresentationStateInner {
  type PresentationState (line 190) | pub(crate) struct PresentationState {
    method async_error_holder (line 195) | pub(crate) fn async_error_holder(&self) -> AsyncPresentationErrorHolder {
    method current_slide_index (line 199) | pub(crate) fn current_slide_index(&self) -> usize {
    method set_current_slide_index (line 203) | fn set_current_slide_index(&self, value: usize) {
  type SlideBuilder (line 210) | pub(crate) struct SlideBuilder {
    method chunks (line 216) | pub(crate) fn chunks(mut self, chunks: Vec<SlideChunk>) -> Self {
    method footer (line 221) | pub(crate) fn footer(mut self, footer: Vec<RenderOperation>) -> Self {
    method build (line 226) | pub(crate) fn build(self) -> Slide {
  type Slide (line 236) | pub(crate) struct Slide {
    method new (line 243) | pub(crate) fn new(chunks: Vec<SlideChunk>, footer: Vec<RenderOperation...
    method iter_operations (line 247) | pub(crate) fn iter_operations(&self) -> impl Iterator<Item = &RenderOp...
    method iter_operations_mut (line 251) | pub(crate) fn iter_operations_mut(&mut self) -> impl Iterator<Item = &...
    method iter_visible_operations (line 255) | pub(crate) fn iter_visible_operations(&self) -> impl Iterator<Item = &...
    method iter_visible_operations_mut (line 259) | pub(crate) fn iter_visible_operations_mut(&mut self) -> impl Iterator<...
    method iter_chunks (line 267) | pub(crate) fn iter_chunks(&self) -> impl Iterator<Item = &SlideChunk> {
    method current_chunk_index (line 271) | pub(crate) fn current_chunk_index(&self) -> usize {
    method jump_chunk (line 275) | pub(crate) fn jump_chunk(&mut self, chunk_index: usize) {
    method current_chunk (line 282) | fn current_chunk(&self) -> &SlideChunk {
    method show_first_chunk (line 286) | fn show_first_chunk(&mut self) {
    method show_all_chunks (line 291) | pub(crate) fn show_all_chunks(&mut self) {
    method move_next (line 298) | fn move_next(&mut self) -> bool {
    method move_previous (line 312) | fn move_previous(&mut self) -> bool {
    method from (line 327) | fn from(operations: Vec<RenderOperation>) -> Self {
  type SlideChunk (line 333) | pub(crate) struct SlideChunk {
    method new (line 339) | pub(crate) fn new(operations: Vec<RenderOperation>, mutators: Vec<Box<...
    method iter_operations (line 343) | pub(crate) fn iter_operations(&self) -> impl Iterator<Item = &RenderOp...
    method pop_last (line 347) | pub(crate) fn pop_last(&mut self) -> Option<RenderOperation> {
    method mutate_next (line 351) | fn mutate_next(&self) -> bool {
    method mutate_previous (line 360) | fn mutate_previous(&self) -> bool {
    method reset_mutations (line 369) | fn reset_mutations(&self) {
    method apply_all_mutations (line 375) | fn apply_all_mutations(&self) {
  type ChunkMutator (line 382) | pub(crate) trait ChunkMutator: Debug {
    method mutate_next (line 383) | fn mutate_next(&self) -> bool;
    method mutate_previous (line 384) | fn mutate_previous(&self) -> bool;
    method reset_mutations (line 385) | fn reset_mutations(&self);
    method apply_all_mutations (line 386) | fn apply_all_mutations(&self);
    method mutations (line 388) | fn mutations(&self) -> (usize, usize);
    method mutate_next (line 508) | fn mutate_next(&self) -> bool {
    method mutate_previous (line 518) | fn mutate_previous(&self) -> bool {
    method reset_mutations (line 528) | fn reset_mutations(&self) {
    method apply_all_mutations (line 532) | fn apply_all_mutations(&self) {
    method mutations (line 536) | fn mutations(&self) -> (usize, usize) {
  type PresentationMetadata (line 393) | pub(crate) struct PresentationMetadata {
    method has_frontmatter (line 432) | pub(crate) fn has_frontmatter(&self) -> bool {
  type PresentationThemeMetadata (line 445) | pub(crate) struct PresentationThemeMetadata {
  type Jump (line 466) | enum Jump {
    method apply (line 477) | fn apply(&self, presentation: &mut Presentation) {
    method repeat (line 490) | fn repeat(&self, count: usize) -> Vec<Self> {
  type DummyMutator (line 496) | struct DummyMutator {
    method new (line 502) | fn new(limit: usize) -> Self {
  function jumping (line 556) | fn jumping(
  function jumping_with_mutations (line 592) | fn jumping_with_mutations(

FILE: src/presentation/poller.rs
  constant POLL_INTERVAL (line 8) | const POLL_INTERVAL: Duration = Duration::from_millis(25);
  type Poller (line 10) | pub(crate) struct Poller {
    method launch (line 16) | pub(crate) fn launch() -> Self {
    method send (line 26) | pub(crate) fn send(&self, command: PollerCommand) {
    method next_effect (line 30) | pub(crate) fn next_effect(&mut self) -> Option<PollableEffect> {
  type PollableEffect (line 37) | pub(crate) enum PollableEffect {
  type PollerCommand (line 46) | pub(crate) enum PollerCommand {
  type PollerWorker (line 54) | struct PollerWorker {
    method new (line 61) | fn new(receiver: Receiver<PollerCommand>, sender: Sender<PollableEffec...
    method run (line 65) | fn run(mut self) {
    method process_command (line 76) | fn process_command(&mut self, command: PollerCommand) {
    method poll (line 96) | fn poll(&mut self) {

FILE: src/presenter.rs
  type PresenterOptions (line 47) | pub struct PresenterOptions {
  type Presenter (line 60) | pub struct Presenter<'a> {
  function new (line 78) | pub fn new(
  function present (line 107) | pub fn present(mut self, path: &Path) -> Result<(), PresentationError> {
  function process_poller_effects (line 180) | fn process_poller_effects(&mut self) -> Result<bool, PresentationError> {
  function publish_event (line 210) | fn publish_event(&self, event: SpeakerNotesEvent) -> io::Result<()> {
  function check_async_error (line 217) | fn check_async_error(&mut self) -> bool {
  function render (line 235) | fn render(&mut self, drawer: &mut TerminalDrawer) -> RenderResult {
  function apply_command (line 256) | fn apply_command(&mut self, command: Command) -> CommandSideEffect {
  function try_reload (line 365) | fn try_reload(&mut self, path: &Path, force: bool) -> RenderResult {
  function try_scale_transition_images (line 393) | fn try_scale_transition_images(&self) -> RenderResult {
  function trigger_slide_async_renders (line 404) | fn trigger_slide_async_renders(presentation: &mut Presentation) -> Vec<B...
  function is_displaying_other_error (line 417) | fn is_displaying_other_error(&self) -> bool {
  function validate_overflows (line 421) | fn validate_overflows(&self, presentation: Presentation) -> PresenterSta...
  function load_presentation (line 438) | fn load_presentation(&mut self, path: &Path) -> Result<Presentation, Loa...
  function toggle_slide_index (line 454) | fn toggle_slide_index(&mut self) {
  function toggle_key_bindings (line 465) | fn toggle_key_bindings(&mut self) {
  function suspend (line 476) | fn suspend(&self, drawer: &mut TerminalDrawer) {
  function animate_next_slide (line 485) | fn animate_next_slide(&mut self, drawer: &mut TerminalDrawer) -> RenderR...
  function animate_previous_slide (line 501) | fn animate_previous_slide(&mut self, drawer: &mut TerminalDrawer) -> Ren...
  function animate_transition (line 521) | fn animate_transition(
  function run_animation (line 550) | fn run_animation<T>(
  function render_frame (line 585) | fn render_frame(commands: &[TerminalCommand<'_>], drawer: &mut TerminalD...
  function virtual_render (line 595) | fn virtual_render(
  function start_automatic_async_renders (line 606) | fn start_automatic_async_renders(&self, presentation: &mut Presentation) {
  type CommandSideEffect (line 620) | enum CommandSideEffect {
  type PresenterState (line 631) | enum PresenterState {
    method failure (line 646) | pub(crate) fn failure<E: Display>(
    method presentation (line 655) | fn presentation(&self) -> &Presentation {
    method presentation_mut (line 665) | fn presentation_mut(&mut self) -> &mut Presentation {
    method into_presentation (line 675) | fn into_presentation(self) -> Presentation {
  type FailureMode (line 686) | enum FailureMode {
  type PresentMode (line 692) | pub enum PresentMode {
  type LoadPresentationError (line 702) | pub enum LoadPresentationError {
  type PresentationError (line 712) | pub enum PresentationError {

FILE: src/render/ascii_scaler.rs
  type AsciiScaler (line 16) | pub(crate) struct AsciiScaler {
    method new (line 21) | pub(crate) fn new(options: RenderEngineOptions) -> Self {
    method process (line 25) | pub(crate) fn process(self, presentation: &Presentation, dimensions: &...
    method scale (line 35) | fn scale(images: Vec<ScalableImage>) {
  type ScalableImage (line 43) | struct ScalableImage {
  type ImageCollector (line 49) | struct ImageCollector {
  method default (line 57) | fn default() -> Self {
  method execute (line 63) | fn execute(&mut self, command: &TerminalCommand<'_>) -> Result<(), Termi...
  method cursor_row (line 99) | fn cursor_row(&self) -> u16 {

FILE: src/render/engine.rs
  constant MINIMUM_LINE_LENGTH (line 26) | const MINIMUM_LINE_LENGTH: u16 = 10;
  type MaxSize (line 29) | pub(crate) struct MaxSize {
  method default (line 37) | fn default() -> Self {
  type RenderEngineOptions (line 48) | pub(crate) struct RenderEngineOptions {
  type RenderEngine (line 53) | pub(crate) struct RenderEngine<'a, T>
  function new (line 70) | pub(crate) fn new(terminal: &'a mut T, window_dimensions: WindowSize, op...
  function starting_rect (line 85) | fn starting_rect(mut dimensions: WindowSize, options: &RenderEngineOptio...
  function render (line 109) | pub(crate) fn render<'b>(mut self, operations: impl Iterator<Item = &'b ...
  function render_one (line 130) | fn render_one(&mut self, operation: &RenderOperation) -> RenderResult {
  function current_rect (line 160) | fn current_rect(&self) -> &WindowRect {
  function current_dimensions (line 165) | fn current_dimensions(&self) -> &WindowSize {
  function current_available_dimensions (line 169) | fn current_available_dimensions(&self) -> WindowSize {
  function clear_screen (line 174) | fn clear_screen(&mut self) -> RenderResult {
  function apply_margin (line 182) | fn apply_margin(&mut self, properties: &MarginProperties) -> RenderResult {
  function pop_margin (line 194) | fn pop_margin(&mut self) -> RenderResult {
  function set_colors (line 202) | fn set_colors(&mut self, colors: &Colors) -> RenderResult {
  function apply_colors (line 207) | fn apply_colors(&mut self) -> RenderResult {
  function jump_to_vertical_center (line 212) | fn jump_to_vertical_center(&mut self) -> RenderResult {
  function jump_to_row (line 220) | fn jump_to_row(&mut self, row: u16) -> RenderResult {
  function jump_to_bottom (line 227) | fn jump_to_bottom(&mut self, index: u16) -> RenderResult {
  function jump_to_column (line 235) | fn jump_to_column(&mut self, column: u16) -> RenderResult {
  function render_text (line 242) | fn render_text(&mut self, text: &WeightedLine, alignment: Alignment) -> ...
  function render_line_break (line 255) | fn render_line_break(&mut self) -> RenderResult {
  function render_image (line 260) | fn render_image(&mut self, image: &Image, properties: &ImageRenderProper...
  function center_cursor (line 306) | fn center_cursor(columns: u16, window: &WindowSize, cursor: &CursorPosit...
  function align_cursor_right (line 312) | fn align_cursor_right(columns: u16, window: &WindowSize, cursor: &Cursor...
  function render_block_line (line 317) | fn render_block_line(&mut self, operation: &BlockLine) -> RenderResult {
  function render_dynamic (line 348) | fn render_dynamic(&mut self, generator: &dyn AsRenderOperations) -> Rend...
  function render_dynamic_top_level (line 356) | fn render_dynamic_top_level(&mut self, generator: &dyn AsRenderOperation...
  function render_async (line 365) | fn render_async(&mut self, generator: &dyn RenderAsync) -> RenderResult {
  function init_column_layout (line 373) | fn init_column_layout(&mut self, widths: &[u8], grid: LayoutGrid, margin...
  function enter_column (line 394) | fn enter_column(&mut self, column_index: usize) -> RenderResult {
  function exit_layout (line 436) | fn exit_layout(&mut self) -> RenderResult {
  function build_layout (line 466) | fn build_layout(&self, alignment: Alignment) -> Layout {
  type LayoutState (line 472) | enum LayoutState {
  type Column (line 491) | struct Column {
  type WindowRect (line 498) | struct WindowRect {
    method shrink_horizontal (line 505) | fn shrink_horizontal(&self, margin: u16) -> Self {
    method shrink_left (line 511) | fn shrink_left(&self, size: u16) -> Self {
    method shrink_right (line 517) | fn shrink_right(&self, size: u16) -> Self {
    method shrink_top (line 522) | fn shrink_top(&self, rows: u16) -> Self {
    method shrink_bottom (line 528) | fn shrink_bottom(&self, rows: u16) -> Self {
  type Instruction (line 555) | enum Instruction {
  type TerminalBuf (line 570) | struct TerminalBuf {
    method push (line 576) | fn push(&mut self, instruction: Instruction) -> io::Result<()> {
    method move_to (line 581) | fn move_to(&mut self, column: u16, row: u16) -> io::Result<()> {
    method move_to_row (line 586) | fn move_to_row(&mut self, row: u16) -> io::Result<()> {
    method move_to_column (line 591) | fn move_to_column(&mut self, column: u16) -> io::Result<()> {
    method move_down (line 595) | fn move_down(&mut self, amount: u16) -> io::Result<()> {
    method move_right (line 599) | fn move_right(&mut self, amount: u16) -> io::Result<()> {
    method move_left (line 603) | fn move_left(&mut self, amount: u16) -> io::Result<()> {
    method move_to_next_line (line 607) | fn move_to_next_line(&mut self) -> io::Result<()> {
    method print_text (line 611) | fn print_text(&mut self, content: &str, _style: &TextStyle) -> io::Res...
    method clear_screen (line 620) | fn clear_screen(&mut self) -> io::Result<()> {
    method set_colors (line 625) | fn set_colors(&mut self, _colors: Colors) -> io::Result<()> {
    method set_background_color (line 629) | fn set_background_color(&mut self, color: Color) -> io::Result<()> {
    method flush (line 633) | fn flush(&mut self) -> io::Result<()> {
    method print_image (line 637) | fn print_image(&mut self, _image: &Image, options: &PrintOptions) -> R...
  method execute (line 644) | fn execute(&mut self, command: &TerminalCommand<'_>) -> Result<(), Termi...
  method cursor_row (line 667) | fn cursor_row(&self) -> u16 {
  type DummyImageScaler (line 672) | struct DummyImageScaler;
  method scale_image (line 675) | fn scale_image(
  method fit_image_to_rect (line 686) | fn fit_image_to_rect(
  function do_render (line 697) | fn do_render(max_size: MaxSize, operations: &[RenderOperation]) -> Vec<I...
  function render (line 707) | fn render(operations: &[RenderOperation]) -> Vec<Instruction> {
  function render_with_max_size (line 711) | fn render_with_max_size(operations: &[RenderOperation]) -> Vec<Instructi...
  function columns (line 722) | fn columns() {
  function bottom_margin (line 755) | fn bottom_margin() {
  function top_margin (line 774) | fn top_margin() {
  function margins (line 784) | fn margins() {
  function nested_margins (line 806) | fn nested_margins() {
  function margin_with_max_size (line 834) | fn margin_with_max_size() {
  function image (line 865) | fn image(#[case] size: ImageSize) {
  function centered_image (line 899) | fn centered_image(#[case] size: ImageSize) {
  function right_aligned_image (line 933) | fn right_aligned_image(#[case] size: ImageSize) {
  function restore_cursor_after_image (line 964) | fn restore_cursor_after_image() {

FILE: src/render/layout.rs
  type Layout (line 4) | pub(crate) struct Layout {
    method new (line 11) | pub(crate) fn new(alignment: Alignment) -> Self {
    method with_start_column (line 15) | pub(crate) fn with_start_column(mut self, column: u16) -> Self {
    method with_font_size (line 20) | pub(crate) fn with_font_size(mut self, font_size: u8) -> Self {
    method compute (line 25) | pub(crate) fn compute(&self, dimensions: &WindowSize, text_length: u16...
    method fit_to_columns (line 67) | fn fit_to_columns(dimensions: &WindowSize, required_fit: u16, actual_f...
  type Positioning (line 73) | pub(crate) struct Positioning {
  function layout (line 170) | fn layout(#[case] alignment: Alignment, #[case] length: u16, #[case] exp...

FILE: src/render/mod.rs
  type RenderResult (line 34) | pub(crate) type RenderResult = Result<(), RenderError>;
  type TerminalDrawerOptions (line 36) | pub(crate) struct TerminalDrawerOptions {
  method default (line 42) | fn default() -> Self {
  type TerminalDrawer (line 48) | pub(crate) struct TerminalDrawer {
    method new (line 54) | pub(crate) fn new(image_printer: Arc<ImagePrinter>, options: TerminalD...
    method render_operations (line 59) | pub(crate) fn render_operations<'a>(
    method render_error (line 69) | pub(crate) fn render_error(&mut self, message: &str, source: &ErrorSou...
    method render_engine_options (line 80) | pub(crate) fn render_engine_options(&self) -> RenderEngineOptions {
    method create_engine (line 84) | fn create_engine(&mut self, dimensions: WindowSize) -> RenderEngine<'_...
  type RenderError (line 92) | pub(crate) enum RenderError {
  type ErrorSource (line 122) | pub(crate) enum ErrorSource {
  type RenderErrorOperation (line 128) | struct RenderErrorOperation {
  method as_render_operations (line 134) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderOpe...

FILE: src/render/operation.rs
  constant DEFAULT_IMAGE_Z_INDEX (line 16) | const DEFAULT_IMAGE_Z_INDEX: i32 = -2;
  type BlockLine (line 20) | pub(crate) struct BlockLine {
  type RenderOperation (line 35) | pub(crate) enum RenderOperation {
  type LayoutGrid (line 106) | pub(crate) enum LayoutGrid {
  type ImageRenderProperties (line 113) | pub(crate) struct ImageRenderProperties {
  method default (line 122) | fn default() -> Self {
  type ImagePosition (line 134) | pub(crate) enum ImagePosition {
  type ImageSize (line 142) | pub(crate) enum ImageSize {
  type MarginProperties (line 153) | pub(crate) struct MarginProperties {
  type AsRenderOperations (line 165) | pub(crate) trait AsRenderOperations: Debug + 'static {
    method as_render_operations (line 167) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderO...
    method diffable_content (line 170) | fn diffable_content(&self) -> Option<&str> {
  type RenderAsync (line 176) | pub(crate) trait RenderAsync: AsRenderOperations {
    method pollable (line 182) | fn pollable(&self) -> Box<dyn Pollable>;
    method start_policy (line 185) | fn start_policy(&self) -> RenderAsyncStartPolicy {
  type RenderAsyncStartPolicy (line 192) | pub(crate) enum RenderAsyncStartPolicy {
  type Pollable (line 201) | pub(crate) trait Pollable: Send + 'static {
    method poll (line 203) | fn poll(&mut self) -> PollableState;
    method poll (line 236) | fn poll(&mut self) -> PollableState {
  type PollableState (line 208) | pub(crate) enum PollableState {
    method is_completed (line 217) | pub(crate) fn is_completed(&self) -> bool {
  type ToggleState (line 225) | pub(crate) struct ToggleState {
    method new (line 230) | pub(crate) fn new(toggled: Arc<Mutex<bool>>) -> Self {

FILE: src/render/properties.rs
  type WindowSize (line 9) | pub(crate) struct WindowSize {
    method current (line 18) | pub(crate) fn current(font_size_fallback: u8) -> io::Result<Self> {
    method shrink_rows (line 41) | pub(crate) fn shrink_rows(&self, amount: u16) -> WindowSize {
    method shrink_columns (line 55) | pub(crate) fn shrink_columns(&self, amount: u16) -> WindowSize {
    method set_columns (line 69) | pub(crate) fn set_columns(&self, amount: u16) -> WindowSize {
    method pixels_per_column (line 76) | pub(crate) fn pixels_per_column(&self) -> f64 {
    method pixels_per_row (line 81) | pub(crate) fn pixels_per_row(&self) -> f64 {
    method aspect_ratio (line 86) | pub(crate) fn aspect_ratio(&self) -> f64 {
    method from (line 92) | fn from(size: crossterm::terminal::WindowSize) -> Self {
    method from (line 98) | fn from((columns, rows): (u16, u16)) -> Self {
  type CursorPosition (line 105) | pub(crate) struct CursorPosition {
  function shrink (line 115) | fn shrink() {

FILE: src/render/text.rs
  type TextDrawer (line 14) | pub(crate) struct TextDrawer<'a> {
  function new (line 28) | pub(crate) fn new(
  function with_surrounding_block (line 63) | pub(crate) fn with_surrounding_block(mut self, block_color: Option<Color...
  function repeat_prefix_on_wrap (line 69) | pub(crate) fn repeat_prefix_on_wrap(mut self, value: bool) -> Self {
  function center_newlines (line 74) | pub(crate) fn center_newlines(mut self, value: bool) -> Self {
  function draw (line 82) | pub(crate) fn draw<T>(self, terminal: &mut T) -> RenderResult
  function print_block_background (line 143) | fn print_block_background<T>(&self, line_length: u16, terminal: &mut T) ...
  type Instruction (line 172) | enum Instruction {
  type TerminalBuf (line 179) | struct TerminalBuf {
    method push (line 185) | fn push(&mut self, instruction: Instruction) -> io::Result<()> {
    method move_to_column (line 190) | fn move_to_column(&mut self, column: u16) -> std::io::Result<()> {
    method move_down (line 194) | fn move_down(&mut self, amount: u16) -> std::io::Result<()> {
    method print_text (line 198) | fn print_text(&mut self, content: &str, style: &TextStyle) -> io::Resu...
    method clear_screen (line 208) | fn clear_screen(&mut self) -> std::io::Result<()> {
    method set_colors (line 212) | fn set_colors(&mut self, _colors: Colors) -> std::io::Result<()> {
    method set_background_color (line 216) | fn set_background_color(&mut self, _color: Color) -> std::io::Result<(...
    method flush (line 220) | fn flush(&mut self) -> std::io::Result<()> {
  method execute (line 226) | fn execute(&mut self, command: &TerminalCommand<'_>) -> Result<(), Termi...
  method cursor_row (line 251) | fn cursor_row(&self) -> u16 {
  type TestDrawer (line 256) | struct TestDrawer {
    method prefix (line 265) | fn prefix<T: Into<WeightedText>>(mut self, prefix: T) -> Self {
    method start_column (line 270) | fn start_column(mut self, column: u16) -> Self {
    method max_line_length (line 275) | fn max_line_length(mut self, length: u16) -> Self {
    method repeat_prefix_on_wrap (line 280) | fn repeat_prefix_on_wrap(mut self) -> Self {
    method center_newlines (line 285) | fn center_newlines(mut self) -> Self {
    method draw (line 290) | fn draw<L: Into<WeightedLine>>(self, line: L) -> Vec<Instruction> {
  method default (line 304) | fn default() -> Self {
  function prefix_on_long_line (line 316) | fn prefix_on_long_line() {
  function prefix_on_long_line_with_font_size (line 331) | fn prefix_on_long_line_with_font_size() {
  function prefix_on_long_line_with_font_size_and_repeat_prefix (line 348) | fn prefix_on_long_line_with_font_size_and_repeat_prefix() {
  function center_newlines (line 366) | fn center_newlines() {

FILE: src/render/validate.rs
  type OverflowValidator (line 13) | pub(crate) struct OverflowValidator;
    method validate (line 16) | pub(crate) fn validate(presentation: &Presentation, dimensions: Window...
  method init (line 35) | fn init(&mut self) -> io::Result<()> {
  method deinit (line 39) | fn deinit(&mut self) {}
  type OverflowError (line 43) | pub(crate) enum OverflowError {

FILE: src/resource.rs
  constant LOOP_INTERVAL (line 23) | const LOOP_INTERVAL: Duration = Duration::from_millis(250);
  type ResourcesInner (line 26) | struct ResourcesInner {
  type Resources (line 40) | pub struct Resources {
    method new (line 48) | pub fn new<P1, P2>(base_path: P1, themes_path: P2, image_registry: Ima...
    method watch_presentation_file (line 65) | pub(crate) fn watch_presentation_file(&self, path: PathBuf) {
    method image (line 71) | pub(crate) fn image<P: AsRef<Path>>(
    method theme_image (line 82) | pub(crate) fn theme_image<P: AsRef<Path>>(&self, path: P) -> Result<Im...
    method theme (line 96) | pub(crate) fn theme<P: AsRef<Path>>(&self, path: P) -> Result<Presenta...
    method external_text_file (line 109) | pub(crate) fn external_text_file<P: AsRef<Path>>(
    method resources_modified (line 126) | pub(crate) fn resources_modified(&self) -> bool {
    method clear_watches (line 131) | pub(crate) fn clear_watches(&self) {
    method clear (line 139) | pub(crate) fn clear(&self) {
    method resolve_path (line 145) | pub(crate) fn resolve_path<P: AsRef<Path>>(&self, path: P, base_path: ...
  type ResourceBasePath (line 157) | pub(crate) enum ResourceBasePath {
  type FileWatcher (line 168) | struct FileWatcher {
    method spawn (line 175) | fn spawn() -> FileWatcherHandle {
    method run (line 186) | fn run(mut self) {
    method handle_event (line 198) | fn handle_event(&mut self, event: WatchEvent) {
    method watches_modified (line 218) | fn watches_modified(&mut self) -> bool {
  type WatchMetadata (line 238) | struct WatchMetadata {
  type FileWatcherHandle (line 244) | struct FileWatcherHandle {
    method send (line 250) | fn send(&self, event: WatchEvent) {
    method has_modifications (line 254) | fn has_modifications(&mut self) -> bool {
  type WatchEvent (line 259) | enum WatchEvent {

FILE: src/terminal/ansi.rs
  type AnsiParser (line 8) | pub(crate) struct AnsiParser {
    method new (line 13) | pub(crate) fn new(current_style: TextStyle) -> Self {
    method parse_lines (line 17) | pub(crate) fn parse_lines<I, S>(self, lines: I) -> (Vec<Line>, TextStyle)
  type AnsiColorParser (line 38) | pub(crate) struct AnsiColorParser {
    method new (line 43) | pub(crate) fn new(starting_style: TextStyle) -> Self {
    method parse_8bit (line 47) | fn parse_8bit(value: u16) -> Option<Color> {
    method parse_color (line 51) | fn parse_color(iter: &mut ParamsIter) -> Option<Color> {
    method try_build_rgb_color (line 67) | fn try_build_rgb_color(r: u16, g: u16, b: u16) -> Option<Color> {
    method parse (line 74) | pub(crate) fn parse(self, mut codes: ParamsIter) -> TextStyle {
  type Handler (line 119) | struct Handler {
    method new (line 126) | fn new(style: TextStyle) -> Self {
    method into_parts (line 130) | fn into_parts(mut self) -> (Line, TextStyle) {
    method save_pending_text (line 135) | fn save_pending_text(&mut self) {
  method print (line 143) | fn print(&mut self, c: char) {
  method csi_dispatch (line 147) | fn csi_dispatch(&mut self, params: &vte::Params, _intermediates: &[u8], ...
  function parse_single (line 212) | fn parse_single(#[case] input: &str, #[case] expected: Line) {
  function resets (line 248) | fn resets(#[case] input: &str, #[case] expected: Line) {

FILE: src/terminal/capabilities.rs
  type TerminalCapabilities (line 23) | pub(crate) struct TerminalCapabilities {
    method is_inside_tmux (line 33) | pub(crate) fn is_inside_tmux() -> bool {
    method query (line 37) | pub(crate) fn query() -> io::Result<Self> {
    method build_capabilities (line 74) | fn build_capabilities(ids: KittyImageIds) -> io::Result<TerminalCapabi...
    method write_kitty_local_query (line 102) | fn write_kitty_local_query(image_id: u32, path: String, tmux: bool) ->...
    method write_kitty_remote_query (line 115) | fn write_kitty_remote_query(image_id: u32, image: &[u8], tmux: bool) -...
    method parse_response (line 131) | fn parse_response<T: io::Read>(mut term: T, ids: KittyImageIds) -> io:...
    method launch_timeout_trigger (line 165) | fn launch_timeout_trigger(running: Arc<AtomicBool>) {
  type RawModeGuard (line 181) | struct RawModeGuard;
    method new (line 184) | fn new() -> io::Result<Self> {
  method drop (line 191) | fn drop(&mut self) {
  type QueryParseState (line 197) | struct QueryParseState {
    method update (line 203) | fn update(&mut self, next: char) -> Option<Response> {
    method build_kitty_response (line 254) | fn build_kitty_response(&self) -> Option<Response> {
  type ResponseType (line 266) | enum ResponseType {
  type Response (line 274) | enum Response {
  type KittyImageIds (line 280) | struct KittyImageIds {
  function detection (line 301) | fn detection(#[case] input: &str, #[case] kitty_local: bool, #[case] kit...

FILE: src/terminal/emulator.rs
  type TerminalEmulator (line 8) | pub enum TerminalEmulator {
    method detect (line 24) | pub fn detect() -> Self {
    method capabilities (line 35) | pub(crate) fn capabilities() -> TerminalCapabilities {
    method disable_capability_detection (line 39) | pub(crate) fn disable_capability_detection() {
    method preferred_protocol (line 43) | pub fn preferred_protocol(&self) -> GraphicsMode {
    method is_detected (line 69) | fn is_detected(&self, term: &str, term_program: &str) -> bool {
    method supports_graphics_mode (line 88) | fn supports_graphics_mode(&self, mode: &GraphicsMode, capabilities: &T...

FILE: src/terminal/image/mod.rs
  type Inner (line 15) | struct Inner {
  type Image (line 24) | pub(crate) struct Image {
    method new (line 31) | pub(crate) fn new(image: TerminalImage, source: ImageSource) -> Self {
    method to_ascii (line 36) | pub(crate) fn to_ascii(&self) -> AsciiImage {
    method image (line 54) | pub(crate) fn image(&self) -> &TerminalImage {
  method eq (line 60) | fn eq(&self, other: &Self) -> bool {
  method fmt (line 66) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type ImageSource (line 73) | pub(crate) enum ImageSource {

FILE: src/terminal/image/printer.rs
  type PrintImage (line 31) | pub(crate) trait PrintImage {
    method register (line 35) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterIma...
    method print (line 37) | fn print<T>(&self, image: &Self::Image, options: &PrintOptions, termin...
    type Image (line 122) | type Image = TerminalImage;
    method register (line 124) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterIma...
    method print (line 136) | fn print<T>(&self, image: &Self::Image, options: &PrintOptions, termin...
  type ImageProperties (line 42) | pub(crate) trait ImageProperties {
    method dimensions (line 43) | fn dimensions(&self) -> (u32, u32);
    method dimensions (line 80) | fn dimensions(&self) -> (u32, u32) {
  type PrintOptions (line 47) | pub(crate) struct PrintOptions {
  type TerminalImage (line 59) | pub(crate) enum TerminalImage {
    method fmt (line 68) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ImagePrinter (line 91) | pub enum ImagePrinter {
    method new (line 107) | pub fn new(mode: GraphicsMode) -> Result<Self, CreatePrinterError> {
  method default (line 101) | fn default() -> Self {
  type ImageRegistry (line 153) | pub(crate) struct ImageRegistry {
    method new (line 159) | pub fn new(printer: Arc<ImagePrinter>) -> Self {
    method fmt (line 165) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method register (line 179) | pub(crate) fn register(&self, spec: ImageSpec) -> Result<Image, Regist...
    method clear (line 199) | pub(crate) fn clear(&self) {
  type ImageSpec (line 204) | pub(crate) enum ImageSpec {
  type CreatePrinterError (line 210) | pub(crate) enum CreatePrinterError {
  type PrintImageError (line 216) | pub(crate) enum PrintImageError {
    method from (line 231) | fn from(e: PaletteColorError) -> Self {
    method from (line 237) | fn from(e: TerminalError) -> Self {
    method other (line 258) | pub(crate) fn other<S>(message: S) -> Self
  type RegisterImageError (line 246) | pub(crate) enum RegisterImageError {

FILE: src/terminal/image/protocols/ascii.rs
  constant TOP_CHAR (line 16) | const TOP_CHAR: &str = "▀";
  constant BOTTOM_CHAR (line 17) | const BOTTOM_CHAR: &str = "▄";
  type Inner (line 19) | struct Inner {
  type AsciiImage (line 25) | pub(crate) struct AsciiImage {
    method cache_scaling (line 30) | pub(crate) fn cache_scaling(&self, columns: u16, rows: u16) {
    method from (line 48) | fn from(image: DynamicImage) -> Self {
  method dimensions (line 42) | fn dimensions(&self) -> (u32, u32) {
  type AsciiPrinter (line 56) | pub struct AsciiPrinter;
    method pixel_color (line 59) | fn pixel_color(pixel: &Rgba<u8>, background: Option<Color>) -> Option<...
  type Image (line 83) | type Image = AsciiImage;
  method register (line 85) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterImage...
  method print (line 96) | fn print<T>(&self, image: &Self::Image, options: &PrintOptions, terminal...

FILE: src/terminal/image/protocols/iterm.rs
  constant CHUNK_SIZE (line 9) | const CHUNK_SIZE: usize = 32 * 1024;
  type ItermImage (line 11) | pub(crate) struct ItermImage {
    method as_rgba8 (line 18) | pub(crate) fn as_rgba8(&self) -> RgbaImage {
  method dimensions (line 26) | fn dimensions(&self) -> (u32, u32) {
  type ItermMode (line 31) | pub enum ItermMode {
  type ItermPrinter (line 36) | pub struct ItermPrinter {
    method new (line 42) | pub(crate) fn new(mode: ItermMode, tmux: bool) -> Self {
  type Image (line 48) | type Image = ItermImage;
  method register (line 50) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterImage...
  method print (line 70) | fn print<T>(&self, image: &Self::Image, options: &PrintOptions, terminal...

FILE: src/terminal/image/protocols/kitty.rs
  constant IMAGE_PLACEHOLDER (line 19) | const IMAGE_PLACEHOLDER: &str = "\u{10EEEE}";
  constant DIACRITICS (line 20) | const DIACRITICS: &[u32] = &[
  type GenericResource (line 44) | enum GenericResource<B> {
  type RawResource (line 49) | type RawResource = GenericResource<RgbaImage>;
    method into_memory_resource (line 52) | fn into_memory_resource(self) -> KittyImage {
  type KittyImage (line 71) | pub(crate) struct KittyImage {
    method as_rgba8 (line 77) | pub(crate) fn as_rgba8(&self) -> RgbaImage {
  method dimensions (line 96) | fn dimensions(&self) -> (u32, u32) {
  type KittyBuffer (line 101) | enum KittyBuffer {
  method drop (line 107) | fn drop(&mut self) {
  type GifFrame (line 114) | struct GifFrame<T> {
  type KittyPrinter (line 119) | pub struct KittyPrinter {
    method new (line 127) | pub(crate) fn new(mode: KittyMode, tmux: bool) -> io::Result<Self> {
    method allocate_tempfile (line 132) | fn allocate_tempfile(&self) -> PathBuf {
    method persist_image (line 137) | fn persist_image(&self, image: RgbaImage) -> io::Result<KittyImage> {
    method persist_gif (line 146) | fn persist_gif(&self, frames: Vec<GifFrame<RgbaImage>>) -> io::Result<...
    method persist_resource (line 160) | fn persist_resource(&self, resource: RawResource) -> io::Result<KittyI...
    method generate_image_id (line 167) | fn generate_image_id() -> u32 {
    method print_image (line 171) | fn print_image<T>(
    method print_gif (line 208) | fn print_gif<T>(
    method make_command (line 286) | fn make_command<'a, P>(&self, options: &'a [ControlOption], payload: P...
    method print_local (line 290) | fn print_local<T>(
    method print_remote (line 310) | fn print_remote<T>(
    method print_unicode_placeholders (line 345) | fn print_unicode_placeholders<T>(
    method load_raw_resource (line 376) | fn load_raw_resource(path: &Path) -> Result<RawResource, RegisterImage...
  type Image (line 396) | type Image = KittyImage;
  method register (line 398) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterImage...
  method print (line 410) | fn print<T>(&self, image: &Self::Image, options: &PrintOptions, terminal...
  type KittyMode (line 423) | pub enum KittyMode {
  type ControlCommand (line 428) | pub(crate) struct ControlCommand<'a, D> {
  function fmt (line 435) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ControlOption (line 457) | pub(crate) enum ControlOption {
    method fmt (line 477) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ImageFormat (line 502) | pub(crate) enum ImageFormat {
    method fmt (line 507) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type TransmissionMedium (line 517) | pub(crate) enum TransmissionMedium {
    method fmt (line 523) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Action (line 534) | pub(crate) enum Action {
    method fmt (line 542) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

FILE: src/terminal/image/protocols/raw.rs
  type RawImage (line 9) | pub(crate) struct RawImage {
    method to_inline_html (line 17) | pub(crate) fn to_inline_html(&self) -> String {
  method dimensions (line 25) | fn dimensions(&self) -> (u32, u32) {
  type RawPrinter (line 30) | pub(crate) struct RawPrinter;
  type Image (line 33) | type Image = RawImage;
  method register (line 35) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterImage...
  method print (line 55) | fn print<T>(&self, _image: &Self::Image, _options: &PrintOptions, _termi...

FILE: src/terminal/image/protocols/sixel.rs
  type SixelImage (line 11) | pub(crate) struct SixelImage(DynamicImage);
    method as_rgba8 (line 14) | pub(crate) fn as_rgba8(&self) -> RgbaImage {
  method dimensions (line 20) | fn dimensions(&self) -> (u32, u32) {
  type SixelPrinter (line 26) | pub struct SixelPrinter;
    method new (line 29) | pub(crate) fn new() -> Result<Self, CreatePrinterError> {
  type Image (line 35) | type Image = SixelImage;
  method register (line 37) | fn register(&self, spec: ImageSpec) -> Result<Self::Image, RegisterImage...
  method print (line 48) | fn print<T>(&self, image: &Self::Image, options: &PrintOptions, terminal...

FILE: src/terminal/image/scale.rs
  type ScaleImage (line 3) | pub(crate) trait ScaleImage {
    method scale_image (line 5) | fn scale_image(
    method fit_image_to_rect (line 15) | fn fit_image_to_rect(
    method scale_image (line 29) | fn scale_image(
    method fit_image_to_rect (line 46) | fn fit_image_to_rect(
  type ImageScaler (line 24) | pub(crate) struct ImageScaler {
  method default (line 87) | fn default() -> Self {
  type TerminalRect (line 93) | pub(crate) struct TerminalRect {
  constant WINDOW (line 103) | const WINDOW: WindowSize = WindowSize { rows: 50, columns: 100, height: ...
  constant SMALL_WINDOW (line 104) | const SMALL_WINDOW: WindowSize = WindowSize { rows: 3, columns: 6, heigh...
  constant OTHER_RATIO (line 105) | const OTHER_RATIO: WindowSize = WindowSize { rows: 10, columns: 10, heig...
  function image_fitting (line 115) | fn image_fitting(

FILE: src/terminal/mod.rs
  type GraphicsMode (line 11) | pub enum GraphicsMode {

FILE: src/terminal/printer.rs
  type TerminalCommand (line 19) | pub(crate) enum TerminalCommand<'a> {
  type TerminalIo (line 38) | pub(crate) trait TerminalIo {
    method execute (line 39) | fn execute(&mut self, command: &TerminalCommand<'_>) -> Result<(), Ter...
    method cursor_row (line 40) | fn cursor_row(&self) -> u16;
    method execute (line 206) | fn execute(&mut self, command: &TerminalCommand<'_>) -> Result<(), Ter...
    method cursor_row (line 229) | fn cursor_row(&self) -> u16 {
  type TerminalError (line 44) | pub(crate) enum TerminalError {
  type Terminal (line 53) | pub(crate) struct Terminal<I: TerminalWrite> {
  function new (line 65) | pub(crate) fn new(mut writer: I, image_printer: Arc<ImagePrinter>) -> io...
  function begin_update (line 80) | fn begin_update(&mut self) -> io::Result<()> {
  function end_update (line 85) | fn end_update(&mut self) -> io::Result<()> {
  function move_to (line 90) | fn move_to(&mut self, column: u16, row: u16) -> io::Result<()> {
  function move_to_row (line 96) | fn move_to_row(&mut self, row: u16) -> io::Result<()> {
  function move_to_column (line 102) | fn move_to_column(&mut self, column: u16) -> io::Result<()> {
  function move_down (line 107) | fn move_down(&mut self, amount: u16) -> io::Result<()> {
  function move_right (line 113) | fn move_right(&mut self, amount: u16) -> io::Result<()> {
  function move_left (line 118) | fn move_left(&mut self, amount: u16) -> io::Result<()> {
  function move_to_next_line (line 123) | fn move_to_next_line(&mut self) -> io::Result<()> {
  function print_text (line 131) | fn print_text(&mut self, content: &str, style: &TextStyle) -> io::Result...
  function clear_screen (line 143) | fn clear_screen(&mut self) -> io::Result<()> {
  function set_colors (line 162) | fn set_colors(&mut self, colors: Colors) -> io::Result<()> {
  function set_background_color (line 172) | fn set_background_color(&mut self, color: Color) -> io::Result<()> {
  function set_cursor_boundaries (line 180) | fn set_cursor_boundaries(&mut self, rows: u16) {
  function flush (line 184) | fn flush(&mut self) -> io::Result<()> {
  function print_image (line 189) | fn print_image(&mut self, image: &Image, options: &PrintOptions) -> Resu...
  function suspend (line 196) | pub(crate) fn suspend(&mut self) {
  function resume (line 200) | pub(crate) fn resume(&mut self) {
  method drop (line 235) | fn drop(&mut self) {
  function should_hide_cursor (line 245) | pub(crate) fn should_hide_cursor() -> bool {
  function is_windows_based_os (line 253) | fn is_windows_based_os() -> bool {
  type TerminalWrite (line 259) | pub(crate) trait TerminalWrite: io::Write {
    method init (line 260) | fn init(&mut self) -> io::Result<()>;
    method deinit (line 261) | fn deinit(&mut self);
    method init (line 265) | fn init(&mut self) -> io::Result<()> {
    method deinit (line 274) | fn deinit(&mut self) {

FILE: src/terminal/virt.rs
  type PrintedImage (line 21) | pub(crate) struct PrintedImage {
  type TerminalRowIterator (line 26) | pub(crate) struct TerminalRowIterator<'a> {
  function new (line 31) | pub(crate) fn new(row: &'a [StyledChar]) -> Self {
  type Item (line 37) | type Item = Text;
  method next (line 39) | fn next(&mut self) -> Option<Self::Item> {
  type TerminalGrid (line 54) | pub(crate) struct TerminalGrid {
  type VirtualTerminal (line 60) | pub(crate) struct VirtualTerminal {
    method new (line 72) | pub(crate) fn new(dimensions: WindowSize, image_behavior: ImageBehavio...
    method into_contents (line 87) | pub(crate) fn into_contents(self) -> TerminalGrid {
    method current_cell_mut (line 91) | fn current_cell_mut(&mut self) -> Option<&mut StyledChar> {
    method set_current_row_height (line 95) | fn set_current_row_height(&mut self, height: u16) {
    method current_row_height (line 101) | fn current_row_height(&self) -> u16 {
    method move_to (line 105) | fn move_to(&mut self, column: u16, row: u16) -> io::Result<()> {
    method move_to_row (line 111) | fn move_to_row(&mut self, row: u16) -> io::Result<()> {
    method move_to_column (line 117) | fn move_to_column(&mut self, column: u16) -> io::Result<()> {
    method move_down (line 122) | fn move_down(&mut self, amount: u16) -> io::Result<()> {
    method move_right (line 127) | fn move_right(&mut self, amount: u16) -> io::Result<()> {
    method move_left (line 132) | fn move_left(&mut self, amount: u16) -> io::Result<()> {
    method move_to_next_line (line 137) | fn move_to_next_line(&mut self) -> io::Result<()> {
    method print_text (line 145) | fn print_text(&mut self, content: &str, style: &TextStyle) -> io::Resu...
    method clear_screen (line 160) | fn clear_screen(&mut self) -> io::Result<()> {
    method set_colors (line 170) | fn set_colors(&mut self, colors: crate::markdown::text_style::Colors) ...
    method set_background_color (line 175) | fn set_background_color(&mut self, color: Color) -> io::Result<()> {
    method flush (line 180) | fn flush(&mut self) -> io::Result<()> {
    method print_image (line 184) | fn print_image(&mut self, image: &Image, options: &PrintOptions) -> Re...
    method fmt (line 202) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  method execute (line 216) | fn execute(&mut self, command: &TerminalCommand<'_>) -> Result<(), Termi...
  method cursor_row (line 238) | fn cursor_row(&self) -> u16 {
  type ImageBehavior (line 244) | pub(crate) enum ImageBehavior {
  type StyledChar (line 251) | pub(crate) struct StyledChar {
    method new (line 258) | pub(crate) fn new(character: char, style: TextStyle) -> Self {
    method from (line 264) | fn from(character: char) -> Self {
  method default (line 270) | fn default() -> Self {
  type TerminalGridExt (line 279) | trait TerminalGridExt {
    method assert_contents (line 280) | fn assert_contents(&self, lines: &[&str]);
    method assert_contents (line 284) | fn assert_contents(&self, lines: &[&str]) {
  function text (line 294) | fn text() {
  function movement (line 307) | fn movement() {
  function iterator (line 324) | fn iterator() {

FILE: src/theme/clean.rs
  constant DEFAULT_CODE_HIGHLIGHT_THEME (line 12) | const DEFAULT_CODE_HIGHLIGHT_THEME: &str = "base16-eighties.dark";
  constant DEFAULT_BLOCK_QUOTE_PREFIX (line 13) | const DEFAULT_BLOCK_QUOTE_PREFIX: &str = "▍ ";
  constant DEFAULT_PROGRESS_BAR_CHAR (line 14) | const DEFAULT_PROGRESS_BAR_CHAR: char = '█';
  constant DEFAULT_FOOTER_HEIGHT (line 15) | const DEFAULT_FOOTER_HEIGHT: u16 = 3;
  constant DEFAULT_TYPST_HORIZONTAL_MARGIN (line 16) | const DEFAULT_TYPST_HORIZONTAL_MARGIN: u16 = 5;
  constant DEFAULT_TYPST_VERTICAL_MARGIN (line 17) | const DEFAULT_TYPST_VERTICAL_MARGIN: u16 = 7;
  constant DEFAULT_MERMAID_THEME (line 18) | const DEFAULT_MERMAID_THEME: &str = "default";
  constant DEFAULT_MERMAID_BACKGROUND (line 19) | const DEFAULT_MERMAID_BACKGROUND: &str = "transparent";
  constant DEFAULT_D2_THEME (line 20) | const DEFAULT_D2_THEME: u32 = 0;
  constant DEFAULT_PTY_CURSOR_SYMBOL (line 21) | const DEFAULT_PTY_CURSOR_SYMBOL: char = '█';
  type ThemeOptions (line 24) | pub(crate) struct ThemeOptions {
    method adjust_font_size (line 29) | fn adjust_font_size(&self, font_size: Option<u8>) -> u8 {
  type PresentationTheme (line 35) | pub(crate) struct PresentationTheme {
    method new (line 60) | pub(crate) fn new(
    method alignment (line 117) | pub(crate) fn alignment(&self, element: &ElementType) -> Alignment {
  type ProcessingThemeError (line 143) | pub(crate) enum ProcessingThemeError {
  type SlideTitleStyle (line 155) | pub(crate) struct SlideTitleStyle {
    method new (line 165) | fn new(
  type HeadingStyles (line 205) | pub(crate) struct HeadingStyles {
    method new (line 215) | fn new(
  type HeadingStyle (line 233) | pub(crate) struct HeadingStyle {
    method new (line 240) | fn new(
  type BlockQuoteStyle (line 262) | pub(crate) struct BlockQuoteStyle {
    method new (line 270) | fn new(raw: &raw::BlockQuoteStyle, palette: &ColorPalette) -> Result<S...
  type AlertStyle (line 284) | pub(crate) struct AlertStyle {
    method new (line 292) | fn new(raw: &raw::AlertStyle, palette: &ColorPalette) -> Result<Self, ...
  type AlertTypeStyles (line 303) | pub(crate) struct AlertTypeStyles {
    method new (line 312) | fn new(
  type AlertTypeStyle (line 354) | pub(crate) struct AlertTypeStyle {
    method new (line 361) | fn new(
  type AlertTypeDefaults (line 376) | struct AlertTypeDefaults {
  type IntroSlideStyle (line 383) | pub(crate) struct IntroSlideStyle {
    method new (line 394) | fn new(
  type IntroSlideLabelStyle (line 413) | pub(crate) struct IntroSlideLabelStyle {
    method new (line 419) | fn new(raw: &raw::BasicStyle, palette: &ColorPalette) -> Result<Self, ...
  type IntroSlideTitleStyle (line 427) | pub(crate) struct IntroSlideTitleStyle {
    method new (line 433) | fn new(
  type AuthorStyle (line 445) | pub(crate) struct AuthorStyle {
    method new (line 452) | fn new(raw: &raw::AuthorStyle, palette: &ColorPalette) -> Result<Self,...
  type DefaultStyle (line 460) | pub(crate) struct DefaultStyle {
    method new (line 467) | fn new(raw: &raw::DefaultStyle, palette: &ColorPalette) -> Result<Self...
  type ColumnLayoutStyle (line 477) | pub(crate) struct ColumnLayoutStyle {
    method new (line 482) | fn new(raw: &raw::ColumnLayoutStyle) -> Self {
  type Alignment (line 490) | pub(crate) enum Alignment {
    method adjust_size (line 497) | pub(crate) fn adjust_size(&self, size: u16) -> u16 {
    method from (line 506) | fn from(alignment: raw::Alignment) -> Self {
  method default (line 516) | fn default() -> Self {
  type FooterStyle (line 522) | pub(crate) enum FooterStyle {
    method new (line 539) | fn new(
    method height (line 562) | pub(crate) fn height(&self) -> u16 {
  type FooterContent (line 571) | pub(crate) enum FooterContent {
    method new (line 577) | fn new(raw: &raw::FooterContent, resources: &Resources) -> Result<Self...
  type CodeBlockStyle (line 589) | pub(crate) struct CodeBlockStyle {
    method new (line 598) | fn new(raw: &raw::CodeBlockStyle) -> Self {
  type PaddingRect (line 616) | pub(crate) struct PaddingRect {
  type ExecutionOutputBlockStyle (line 625) | pub(crate) struct ExecutionOutputBlockStyle {
    method new (line 632) | fn new(raw: &raw::ExecutionOutputBlockStyle, palette: &ColorPalette) -...
  type ExecutionStatusBlockStyle (line 645) | pub(crate) struct ExecutionStatusBlockStyle {
    method new (line 653) | fn new(raw: &raw::ExecutionStatusBlockStyle, palette: &ColorPalette) -...
  type PtyOutputBlockStyle (line 664) | pub(crate) struct PtyOutputBlockStyle {
    method new (line 671) | fn new(raw: &raw::PtyOutputBlockStyle, palette: &ColorPalette) -> Resu...
  type PtyCursorStyle (line 685) | pub(crate) struct PtyCursorStyle {
    method new (line 691) | fn new(raw: &raw::PtyCursorStyle, palette: &ColorPalette) -> Result<Se...
  type PtyStandbyStyle (line 700) | pub(crate) enum PtyStandbyStyle {
    method as_lines (line 706) | pub(crate) fn as_lines(&self) -> &[&str] {
  type ModifierStyle (line 728) | pub(crate) struct ModifierStyle {
    method new (line 733) | fn new(raw: &raw::ModifierStyle, palette: &ColorPalette) -> Result<Sel...
  type ElementType (line 741) | pub(crate) enum ElementType {
  type TypstStyle (line 762) | pub(crate) struct TypstStyle {
    method new (line 769) | fn new(raw: &raw::TypstStyle, palette: &ColorPalette) -> Result<Self, ...
  type MermaidStyle (line 779) | pub(crate) struct MermaidStyle {
    method new (line 785) | fn new(raw: &raw::MermaidStyle) -> Self {
  type D2Style (line 794) | pub(crate) struct D2Style {
    method new (line 799) | fn new(raw: &raw::D2Style) -> Self {
  type ModalStyle (line 807) | pub(crate) struct ModalStyle {
    method new (line 813) | fn new(
  type LayoutGridStyle (line 829) | pub(crate) struct LayoutGridStyle {
    method new (line 834) | fn new(
  type ColorPalette (line 850) | pub(crate) struct ColorPalette {
    type Error (line 856) | type Error = ProcessingThemeError;
    method try_from (line 858) | fn try_from(palette: &raw::ColorPalette) -> Result<Self, Self::Error> {

FILE: src/theme/raw.rs
  type RawColors (line 12) | pub(crate) type RawColors = Colors<RawColor>;
  type PresentationTheme (line 17) | pub struct PresentationTheme {
    method from_path (line 109) | pub(crate) fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, LoadT...
  type SlideTitleStyle (line 119) | pub(crate) struct SlideTitleStyle {
  type HeadingStyles (line 163) | pub(crate) struct HeadingStyles {
  type HeadingStyle (line 191) | pub(crate) struct HeadingStyle {
  type BlockQuoteStyle (line 225) | pub(crate) struct BlockQuoteStyle {
  type BlockQuoteColors (line 243) | pub(crate) struct BlockQuoteColors {
  type AlertStyle (line 255) | pub(crate) struct AlertStyle {
  type AlertTypeStyles (line 277) | pub(crate) struct AlertTypeStyles {
  type AlertTypeStyle (line 301) | pub(crate) struct AlertTypeStyle {
  type IntroSlideStyle (line 317) | pub(crate) struct IntroSlideStyle {
  type DefaultStyle (line 349) | pub(crate) struct DefaultStyle {
  type ColumnLayoutStyle (line 365) | pub(crate) struct ColumnLayoutStyle {
  type BasicStyle (line 373) | pub(crate) struct BasicStyle {
  type IntroSlideTitleStyle (line 385) | pub(crate) struct IntroSlideTitleStyle {
  type Alignment (line 404) | pub(crate) enum Alignment {
  method default (line 432) | fn default() -> Self {
  type AuthorStyle (line 439) | pub(crate) struct AuthorStyle {
  type FooterStyle (line 456) | pub(crate) enum FooterStyle {
  method default (line 491) | fn default() -> Self {
  type FooterTemplateChunk (line 497) | pub(crate) enum FooterTemplateChunk {
  type FooterContent (line 513) | pub(crate) enum FooterContent {
    method deserialize (line 554) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  type FooterContentVisitor (line 521) | struct FooterContentVisitor;
    type Value (line 524) | type Value = FooterContent;
    method expecting (line 526) | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    method visit_str (line 530) | fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    method visit_map (line 538) | fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
  type FooterTemplate (line 563) | pub(crate) struct FooterTemplate(pub(crate) Vec<FooterTemplateChunk>);
    method fmt (line 636) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Err (line 569) | type Err = ParseFooterTemplateError;
  method from_str (line 571) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type ParseFooterTemplateError (line 658) | pub(crate) enum ParseFooterTemplateError {
  type CodeBlockStyle (line 674) | pub(crate) struct CodeBlockStyle {
  type ExecutionOutputBlockStyle (line 697) | pub(crate) struct ExecutionOutputBlockStyle {
  type PtyOutputBlockStyle (line 713) | pub(crate) struct PtyOutputBlockStyle {
  type PtyCursorStyle (line 728) | pub(crate) struct PtyCursorStyle {
  type PtyStandbyStyle (line 740) | pub(crate) enum PtyStandbyStyle {
  type ExecutionStatusBlockStyle (line 747) | pub(crate) struct ExecutionStatusBlockStyle {
  type ModifierStyle (line 766) | pub(crate) struct ModifierStyle {
  type PaddingRect (line 774) | pub(crate) struct PaddingRect {
  type Margin (line 787) | pub(crate) enum Margin {
    method as_characters (line 796) | pub(crate) fn as_characters(&self, screen_size: u16) -> u16 {
    method is_empty (line 806) | pub(crate) fn is_empty(&self) -> bool {
  method default (line 812) | fn default() -> Self {
  type AuthorPositioning (line 820) | pub(crate) enum AuthorPositioning {
  type TypstStyle (line 831) | pub(crate) struct TypstStyle {
  type MermaidStyle (line 845) | pub(crate) struct MermaidStyle {
  type D2Style (line 855) | pub(crate) struct D2Style {
  type ModalStyle (line 862) | pub(crate) struct ModalStyle {
  type LayoutGridStyle (line 874) | pub(crate) struct LayoutGridStyle {
  type ColorPalette (line 882) | pub(crate) struct ColorPalette {
  type RawColor (line 891) | pub(crate) enum RawColor {
    method new_palette (line 902) | fn new_palette(name: &str) -> Result<Self, ParseColorError> {
    method resolve (line 906) | pub(crate) fn resolve(
    method from (line 927) | fn from(color: Color) -> Self {
    method fmt (line 971) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Err (line 933) | type Err = ParseColorError;
  method from_str (line 935) | fn from_str(input: &str) -> Result<Self, Self::Err> {
  type ParseColorError (line 999) | pub(crate) enum ParseColorError {
  function parse_all_footer_template_variables (line 1016) | fn parse_all_footer_template_variables() {
  function parse_double_braces (line 1043) | fn parse_double_braces() {
  function invalid_footer_templates (line 1062) | fn invalid_footer_templates(#[case] input: &str) {
  function color_serde (line 1067) | fn color_serde() {
  function invalid_palette_color_names (line 1078) | fn invalid_palette_color_names(#[case] input: &str) {
  function valid_palette_color_names (line 1085) | fn valid_palette_color_names(#[case] input: &str, #[case] expected: &str) {

FILE: src/theme/registry.rs
  type PresentationThemeRegistry (line 11) | pub struct PresentationThemeRegistry {
    method load_by_name (line 17) | pub fn load_by_name(&self, name: &str) -> Option<PresentationTheme> {
    method register_from_directory (line 29) | pub fn register_from_directory<P: AsRef<Path>>(&mut self, path: P) -> ...
    method extend_theme (line 69) | fn extend_theme(&mut self, theme_name: &str) -> Result<(), LoadThemeEr...
    method theme_names (line 83) | pub fn theme_names(&self) -> Vec<String> {
  type ThemeGraph (line 90) | struct ThemeGraph {
    method new (line 96) | fn new<I>(dependencies: I) -> Self
    method pop (line 116) | fn pop(&mut self) -> Option<String> {
  type LoadThemeError (line 127) | pub enum LoadThemeError {
  function write_theme (line 154) | fn write_theme(name: &str, theme: PresentationTheme, directory: &TempDir) {
  function validate_themes (line 161) | fn validate_themes() {
  function load_custom (line 180) | fn load_custom() {
  function load_derive_chain (line 199) | fn load_derive_chain() {
  function invalid_derives (line 215) | fn invalid_derives() {
  function load_derive_chain_loop (line 228) | fn load_derive_chain_loop() {
  function register_from_missing_directory (line 240) | fn register_from_missing_directory() {

FILE: src/third_party.rs
  type ThirdPartyConfigs (line 31) | pub struct ThirdPartyConfigs {
  type ThirdPartyRender (line 40) | pub struct ThirdPartyRender {
    method new (line 45) | pub fn new(config: ThirdPartyConfigs, image_registry: ImageRegistry, r...
    method render (line 55) | pub(crate) fn render(
  method default (line 68) | fn default() -> Self {
  type ThirdPartyRenderRequest (line 82) | pub(crate) enum ThirdPartyRenderRequest {
  type RenderResult (line 90) | enum RenderResult {
  type RenderPoolState (line 97) | struct RenderPoolState {
  type Shared (line 103) | struct Shared {
  type RenderPool (line 109) | struct RenderPool {
    method new (line 115) | fn new(config: ThirdPartyConfigs, root_dir: String, image_registry: Im...
    method render (line 128) | fn render(&self, request: ThirdPartyRenderRequest) -> Arc<Mutex<Render...
  type Worker (line 137) | struct Worker {
    method run (line 143) | fn run(self) {
    method render (line 159) | fn render(&self, request: ThirdPartyRenderRequest, result: Arc<Mutex<R...
    method render_typst (line 173) | pub(crate) fn render_typst(&self, input: String, style: &TypstStyle) -...
    method render_latex (line 181) | pub(crate) fn render_latex(&self, input: String, style: &TypstStyle) -...
    method render_mermaid (line 194) | pub(crate) fn render_mermaid(&self, input: String, style: &MermaidStyl...
    method render_d2 (line 230) | pub(crate) fn render_d2(&self, input: String, style: &D2Style) -> Resu...
    method do_render_typst (line 251) | fn do_render_typst(
    method generate_page_header (line 281) | fn generate_page_header(style: &TypstStyle) -> Result<String, ThirdPar...
    method as_typst_color (line 301) | fn as_typst_color(color: &Color) -> Result<String, ThirdPartyRenderErr...
    method load_image (line 308) | fn load_image(&self, snippet: ImageSnippet, path: &Path) -> Result<Ima...
  type ThirdPartyRenderError (line 318) | pub enum ThirdPartyRenderError {
  type SnippetSource (line 336) | enum SnippetSource {
  type ImageSnippet (line 344) | struct ImageSnippet {
  type RenderThirdParty (line 350) | pub(crate) struct RenderThirdParty {
    method new (line 358) | fn new(pending_result: Arc<Mutex<RenderResult>>, default_style: TextSt...
  method pollable (line 364) | fn pollable(&self) -> Box<dyn Pollable> {
  method start_policy (line 368) | fn start_policy(&self) -> RenderAsyncStartPolicy {
  method as_render_operations (line 374) | fn as_render_operations(&self, _: &WindowSize) -> Vec<RenderOperation> {
  type Output (line 402) | enum Output {
  type OperationPollable (line 408) | struct OperationPollable {
  method poll (line 414) | fn poll(&mut self) -> PollableState {

FILE: src/tools.rs
  constant DEFAULT_MAX_ERROR_LINES (line 7) | const DEFAULT_MAX_ERROR_LINES: usize = 10;
  type ThirdPartyTools (line 9) | pub(crate) struct ThirdPartyTools;
    method pandoc (line 12) | pub(crate) fn pandoc(args: &[&str]) -> Tool {
    method typst (line 16) | pub(crate) fn typst(args: &[&str]) -> Tool {
    method mermaid (line 20) | pub(crate) fn mermaid(args: &[&str]) -> Tool {
    method d2 (line 25) | pub(crate) fn d2(args: &[&str]) -> Tool {
    method weasyprint (line 29) | pub(crate) fn weasyprint(args: &[&str]) -> Tool {
  type Tool (line 34) | pub(crate) struct Tool {
    method new (line 42) | fn new(command_name: &'static str, args: &[&str]) -> Self {
    method stdin (line 48) | pub(crate) fn stdin(mut self, stdin: Vec<u8>) -> Self {
    method inherit_stdout (line 53) | pub(crate) fn inherit_stdout(mut self) -> Self {
    method max_error_lines (line 58) | pub(crate) fn max_error_lines(mut self, value: usize) -> Self {
    method run (line 63) | pub(crate) fn run(self) -> Result<(), ExecutionError> {
    method run_and_capture_stdout (line 68) | pub(crate) fn run_and_capture_stdout(mut self) -> Result<Vec<u8>, Exec...
    method spawn (line 75) | fn spawn(mut self) -> Result<Output, ExecutionError> {
    method validate_output (line 97) | fn validate_output(self, output: &Output) -> Result<(), ExecutionError> {
  type ExecutionError (line 108) | pub enum ExecutionError {

FILE: src/transitions/collapse_horizontal.rs
  type CollapseHorizontalAnimation (line 4) | pub(crate) struct CollapseHorizontalAnimation {
    method new (line 10) | pub(crate) fn new(left: TerminalGrid, right: TerminalGrid, direction: ...
  type Frame (line 20) | type Frame = LinesFrame;
  method build_frame (line 22) | fn build_frame(&self, frame: usize, _previous_frame: usize) -> Self::Fra...
  method total_frames (line 38) | fn total_frames(&self) -> usize {
  function as_text (line 49) | fn as_text(line: Line) -> String {
  function transition (line 58) | fn transition(#[case] frame: usize, #[case] expected: &[&str]) {

FILE: src/transitions/fade.rs
  type FadeAnimation (line 11) | pub(crate) struct FadeAnimation {
    method new (line 16) | pub(crate) fn new(left: TerminalGrid, right: TerminalGrid, direction: ...
  type Frame (line 48) | type Frame = FadeCellsFrame;
  method build_frame (line 50) | fn build_frame(&self, frame: usize, previous_frame: usize) -> Self::Frame {
  method total_frames (line 58) | fn total_frames(&self) -> usize {
  type FadeCellsFrame (line 64) | pub(crate) struct FadeCellsFrame {
  method build_commands (line 69) | fn build_commands(&self) -> Vec<TerminalCommand<'_>> {
  type Change (line 84) | struct Change {
  function transition (line 104) | fn transition(#[case] direction: TransitionDirection) {

FILE: src/transitions/mod.rs
  type TransitionDirection (line 16) | pub(crate) enum TransitionDirection {
  type AnimateTransition (line 21) | pub(crate) trait AnimateTransition {
    method build_frame (line 24) | fn build_frame(&self, frame: usize, previous_frame: usize) -> Self::Fr...
    method total_frames (line 25) | fn total_frames(&self) -> usize;
  type AnimationFrame (line 28) | pub(crate) trait AnimationFrame {
    method build_commands (line 29) | fn build_commands(&self) -> Vec<TerminalCommand<'_>>;
    method build_commands (line 67) | fn build_commands(&self) -> Vec<TerminalCommand<'_>> {
  type LinesFrame (line 33) | pub(crate) struct LinesFrame {
    method skip_whitespace (line 39) | fn skip_whitespace(mut text: &str) -> (&str, usize, usize) {
    method from (line 56) | fn from(grid: &TerminalGrid) -> Self {
  function build_grid (line 117) | pub(crate) fn build_grid(rows: &[&str]) -> TerminalGrid {
  function commands (line 132) | fn commands() {

FILE: src/transitions/slide_horizontal.rs
  type SlideHorizontalAnimation (line 8) | pub(crate) struct SlideHorizontalAnimation {
    method new (line 15) | pub(crate) fn new(
  type Frame (line 32) | type Frame = LinesFrame;
  method build_frame (line 34) | fn build_frame(&self, frame: usize, _previous_frame: usize) -> Self::Fra...
  method total_frames (line 64) | fn total_frames(&self) -> usize {
  function as_text (line 74) | fn as_text(line: Line) -> String {
  function build_frame (line 87) | fn build_frame(#[case] frame: usize, #[case] direction: TransitionDirect...

FILE: src/ui/execution/acquire_terminal.rs
  constant MINIMUM_SEPARATOR_WIDTH (line 23) | const MINIMUM_SEPARATOR_WIDTH: u16 = 32;
  type RunAcquireTerminalSnippet (line 26) | pub(crate) struct RunAcquireTerminalSnippet {
    method new (line 36) | pub(crate) fn new(
    method invoke (line 46) | fn invoke(&self) -> Result<(), String> {
  method as_render_operations (line 68) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  method pollable (line 101) | fn pollable(&self) -> Box<dyn Pollable> {
  type State (line 118) | enum State {
    method fmt (line 126) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type OperationPollable (line 135) | struct OperationPollable;
  method poll (line 138) | fn poll(&mut self) -> PollableState {

FILE: src/ui/execution/disabled.rs
  type SnippetExecutionDisabledOperation (line 12) | pub(crate) struct SnippetExecutionDisabledOperation {
    method new (line 20) | pub(crate) fn new(
  method as_render_operations (line 37) | fn as_render_operations(&self, _: &WindowSize) -> Vec<RenderOperation> {
  method pollable (line 50) | fn pollable(&self) -> Box<dyn Pollable> {
  method start_policy (line 54) | fn start_policy(&self) -> RenderAsyncStartPolicy {
  type ExecutionType (line 60) | pub(crate) enum ExecutionType {

FILE: src/ui/execution/image.rs
  type RunImageSnippet (line 28) | pub(crate) struct RunImageSnippet {
    method new (line 36) | pub(crate) fn new(
  method pollable (line 48) | fn pollable(&self) -> Box<dyn Pollable> {
  method start_policy (line 56) | fn start_policy(&self) -> RenderAsyncStartPolicy {
  method as_render_operations (line 62) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  type OperationPollable (line 83) | struct OperationPollable {
    method load_image (line 90) | fn load_image(&self, data: &[u8]) -> Result<Image, String> {
  method poll (line 102) | fn poll(&mut self) -> PollableState {
  type State (line 151) | enum State {

FILE: src/ui/execution/output.rs
  constant MINIMUM_SEPARATOR_WIDTH (line 31) | const MINIMUM_SEPARATOR_WIDTH: u16 = 32;
  type State (line 34) | enum State {
  type Inner (line 42) | struct Inner {
  type SnippetOutputOperation (line 53) | pub(crate) struct SnippetOutputOperation {
    method new (line 64) | pub(crate) fn new(
  method as_render_operations (line 78) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  type OperationPollable (line 122) | struct OperationPollable {
    method try_start (line 128) | fn try_start(&self, inner: &mut Inner) {
  method poll (line 144) | fn poll(&mut self) -> PollableState {
  type SnippetHandle (line 193) | pub(crate) struct SnippetHandle(Arc<Mutex<Inner>>);
    method new (line 196) | pub(crate) fn new(code: Snippet, executor: LanguageSnippetExecutor, po...
    method snippet (line 209) | pub(crate) fn snippet(&self) -> Snippet {
  type RunSnippetTrigger (line 215) | pub(crate) struct RunSnippetTrigger(Arc<Mutex<Inner>>);
    method new (line 218) | pub(crate) fn new(handle: SnippetHandle) -> Self {
  method as_render_operations (line 224) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  method pollable (line 230) | fn pollable(&self) -> Box<dyn Pollable> {
  method start_policy (line 234) | fn start_policy(&self) -> RenderAsyncStartPolicy {
  type ExecIndicatorStyle (line 240) | pub(crate) struct ExecIndicatorStyle {
  type WrappedSnippetHandle (line 248) | pub(crate) enum WrappedSnippetHandle {
    method process_status (line 254) | pub(crate) fn process_status(&self) -> Option<ProcessStatus> {
    method build_trigger (line 261) | pub(crate) fn build_trigger(&self) -> Box<dyn RenderAsync> {
    method from (line 270) | fn from(handle: SnippetHandle) -> Self {
    method from (line 276) | fn from(handle: PtySnippetHandle) -> Self {
  type ExecIndicator (line 282) | pub(crate) struct ExecIndicator {
    method new (line 290) | pub(crate) fn new<T: Into<WrappedSnippetHandle>>(handle: T, style: Exe...
  method as_render_operations (line 307) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  function make_run_shell (line 340) | fn make_run_shell(code: &str) -> RunSnippetTrigger {
  function run_command (line 356) | fn run_command() {
  function multiple_pollables (line 369) | fn multiple_pollables() {

FILE: src/ui/execution/pty.rs
  constant DEFAULT_COLUMNS (line 27) | const DEFAULT_COLUMNS: u16 = 80;
  constant DEFAULT_ROWS (line 28) | const DEFAULT_ROWS: u16 = 24;
  type State (line 31) | enum State {
  type Inner (line 42) | struct Inner {
    method fmt (line 55) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type PtySnippetOutputOperation (line 71) | pub(crate) struct PtySnippetOutputOperation {
    method new (line 78) | pub(crate) fn new(handle: PtySnippetHandle, style: PtyOutputBlockStyle...
    method standby_row (line 82) | fn standby_row(&self, row: u16, dimensions: &WindowSize) -> Line {
  method as_render_operations (line 97) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderOpe...
  method pollable (line 196) | fn pollable(&self) -> Box<dyn Pollable> {
  type OperationPollable (line 202) | struct OperationPollable {
    method spawn (line 207) | fn spawn(ctx: PtySnippetContext, dimensions: WindowSize, handle: PtySn...
  method poll (line 222) | fn poll(&mut self) -> PollableState {
  type PtyMaster (line 266) | pub(crate) struct PtyMaster {
    method new (line 272) | fn new(master: Box<dyn MasterPty>, handle: PtySnippetHandle, ctx: PtyS...
    method fmt (line 280) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function process_output (line 285) | fn process_output(mut reader: Box<dyn io::Read>, handle: PtySnippetHandl...
  method from (line 305) | fn from(cell: &vt100::Cell) -> Self {
  function parse_color (line 322) | fn parse_color(color: vt100::Color) -> Option<Color> {
  type PtySnippetHandle (line 331) | pub(crate) struct PtySnippetHandle(Arc<Mutex<Inner>>);
    method new (line 334) | pub(crate) fn new(
    method snippet (line 362) | pub(crate) fn snippet(&self) -> Snippet {
    method process_status (line 366) | pub(crate) fn process_status(&self) -> Option<ProcessStatus> {
  type RunPtySnippetTrigger (line 376) | pub(crate) struct RunPtySnippetTrigger(PtySnippetHandle);
    method new (line 379) | pub(crate) fn new(handle: PtySnippetHandle) -> Self {
  method as_render_operations (line 385) | fn as_render_operations(&self, _dimensions: &WindowSize) -> Vec<RenderOp...
  method pollable (line 391) | fn pollable(&self) -> Box<dyn Pollable> {
  method start_policy (line 395) | fn start_policy(&self) -> RenderAsyncStartPolicy {

FILE: src/ui/execution/validator.rs
  type ValidateSnippetOperation (line 17) | pub(crate) struct ValidateSnippetOperation {
    method new (line 24) | pub(crate) fn new(snippet: Snippet, executor: LanguageSnippetExecutor)...
  method as_render_operations (line 30) | fn as_render_operations(&self, _dimensions: &crate::WindowSize) -> Vec<R...
  method pollable (line 36) | fn pollable(&self) -> Box<dyn Pollable> {
  method start_policy (line 44) | fn start_policy(&self) -> RenderAsyncStartPolicy {
  type State (line 50) | enum State {
  type OperationPollable (line 57) | struct OperationPollable {
    method success_to_pollable_state (line 64) | fn success_to_pollable_state(&self) -> PollableState {
    method error_to_pollable_state (line 73) | fn error_to_pollable_state<S: Into<String>>(&self, error: S) -> Pollab...
  method poll (line 82) | fn poll(&mut self) -> PollableState {
  function expectation_matches (line 124) | fn expectation_matches(#[case] contents: &str, #[case] expected_executio...
  function expect_does_not_match (line 148) | fn expect_does_not_match(

FILE: src/ui/footer.rs
  type FooterVariables (line 19) | pub(crate) struct FooterVariables {
  type FooterGenerator (line 31) | pub(crate) struct FooterGenerator {
    method new (line 38) | pub(crate) fn new(
    method render_line (line 49) | fn render_line(line: &FooterLine, alignment: Alignment, height: u16, o...
    method push_image (line 56) | fn push_image(&self, image: &Image, alignment: Alignment, height: u16,...
  method as_render_operations (line 84) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderOpe...
  type RenderedFooterStyle (line 137) | enum RenderedFooterStyle {
    method new (line 152) | fn new(
  type FooterLine (line 171) | struct FooterLine(Line);
    method new (line 174) | fn new(
    method extract_variable (line 222) | fn extract_variable<'a>(
  type RenderedFooterContent (line 231) | enum RenderedFooterContent {
    method new (line 237) | fn new(
  type InvalidFooterTemplateError (line 251) | pub(crate) enum InvalidFooterTemplateError {
  function render_valid (line 306) | fn render_valid(#[case] chunk: FooterTemplateChunk, #[case] expected: &[...
  function render_invalid (line 320) | fn render_invalid(#[case] chunk: FooterTemplateChunk) {
  function interleaved_spans (line 326) | fn interleaved_spans() {

FILE: src/ui/modals.rs
  type IndexBuilder (line 26) | pub(crate) struct IndexBuilder {
    method add_title (line 32) | pub(crate) fn add_title(&mut self, title: Line) {
    method set_background (line 36) | pub(crate) fn set_background(&mut self, background: Image) {
    method build (line 40) | pub(crate) fn build(self, theme: &PresentationTheme, state: Presentati...
  type IndexDrawer (line 65) | struct IndexDrawer {
  method as_render_operations (line 76) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderOpe...
  type KeyBindingsModalBuilder (line 104) | pub(crate) struct KeyBindingsModalBuilder {
    method set_background (line 109) | pub(crate) fn set_background(&mut self, background: Image) {
    method build (line 113) | pub(crate) fn build(self, theme: &PresentationTheme, config: &KeyBindi...
    method build_line (line 138) | fn build_line(label: &str, bindings: &[KeyBinding]) -> Line {
  type ModalBuilder (line 150) | struct ModalBuilder {
    method new (line 156) | fn new<S: Into<String>>(heading: S) -> Self {
    method build (line 160) | fn build(self, style: TextStyle) -> ModalContent {
    method center_line (line 187) | fn center_line(text: String, longest_line: usize) -> String {
    method build_line (line 196) | fn build_line(text_chunks: Vec<Text>, content_width: u16) -> ContentRow {
  type ModalContent (line 209) | struct ModalContent {
    method into_operations (line 217) | fn into_operations(self) -> Vec<RenderOperation> {
  type ContentRow (line 231) | struct ContentRow {
    method with_style (line 238) | fn with_style(mut self, style: TextStyle) -> ContentRow {
    method build (line 245) | fn build(self) -> WeightedLine {
  type Border (line 253) | enum Border {
    method render_line (line 261) | fn render_line(&self, content_length: u16) -> [RenderOperation; 2] {
    method edges (line 273) | fn edges(&self) -> (char, char) {
  type CenterModalContent (line 284) | struct CenterModalContent {
    method new (line 291) | fn new(content_width: u16, content_height: usize, background: Option<I...
  method as_render_operations (line 297) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderOpe...
  method from (line 321) | fn from(op: CenterModalContent) -> Self {

FILE: src/ui/separator.rs
  type SeparatorWidth (line 16) | pub(crate) enum SeparatorWidth {
  type RenderSeparator (line 24) | pub(crate) struct RenderSeparator {
    method new (line 31) | pub(crate) fn new<S: Into<Line>>(heading: S, width: SeparatorWidth, fo...
  method from (line 39) | fn from(separator: RenderSeparator) -> Self {
  method as_render_operations (line 45) | fn as_render_operations(&self, dimensions: &WindowSize) -> Vec<RenderOpe...

FILE: src/utils.rs
  function deserialize_from_str (line 38) | pub(crate) fn deserialize_from_str<'de, D, T>(deserializer: D) -> Result...
  function serialize_display (line 69) | pub(crate) fn serialize_display<T, S>(value: &T, serializer: S) -> Resul...
Condensed preview — 155 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,156K chars).
[
  {
    "path": ".editorconfig",
    "chars": 44,
    "preview": "[*.sh]\nindent_style = space\nindent_size = 4\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 19,
    "preview": "github: mfontanini\n"
  },
  {
    "path": ".github/workflows/docs.yaml",
    "chars": 741,
    "preview": "name: Deploy docs\n\non:\n  push:\n    branches:\n      - master\n\npermissions:\n  contents: write\n\njobs:\n  build-and-deploy:\n "
  },
  {
    "path": ".github/workflows/merge.yaml",
    "chars": 2204,
    "preview": "on:\n  pull_request:\n  push:\n    branches:\n      - master\n\nname: Merge checks\n\njobs:\n  check:\n    name: Checks\n    runs-o"
  },
  {
    "path": ".github/workflows/nightly.yaml",
    "chars": 4266,
    "preview": "name: Nightly build\n\non:\n  schedule:\n    - cron: \"0 0 * * *\"\n\nenv:\n  RELEASE_VERSION: nightly\n\njobs:\n  vars:\n    name: S"
  },
  {
    "path": ".github/workflows/release.yaml",
    "chars": 4062,
    "preview": "name: Release\n\non:\n  push:\n    tags:\n      - \"v*.*.*\"\n\njobs:\n  changelog:\n    name: Parse changelog\n    runs-on: ubuntu-"
  },
  {
    "path": ".gitignore",
    "chars": 8,
    "preview": "/target\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 57419,
    "preview": "# v0.16.1 - 2026-02-19\n\n## New features\n\n* Allow `italic` to be used as well as `italics` in theme ([#847](https://githu"
  },
  {
    "path": "Cargo.toml",
    "chars": 1652,
    "preview": "[package]\nname = \"presenterm\"\nauthors = [\"Matias Fontanini\"]\ndescription = \"A terminal slideshow presentation tool\"\nrepo"
  },
  {
    "path": "LICENSE",
    "chars": 1326,
    "preview": "BSD 2-Clause License\n\nCopyright (c) 2023, Matias Fontanini\nAll rights reserved.\n\nRedistribution and use in source and bi"
  },
  {
    "path": "README.md",
    "chars": 6758,
    "preview": "presenterm\n===\n\n[![crates-badge]][crates-package] [![brew-badge]][brew-package] [![nix-badge]][nix-package] \n[![arch-bad"
  },
  {
    "path": "bat/bat.git-hash",
    "chars": 41,
    "preview": "0e469634a3e8987fd7085520e1f90cd83d8fe51b\n"
  },
  {
    "path": "bat/syntaxes.git-hash",
    "chars": 41,
    "preview": "3d87b25b190e0990e0e75a2ab8f994d6c277d263\n"
  },
  {
    "path": "bat/update.sh",
    "chars": 690,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nif [ $# -ne 1 ]; then\n    echo \"Usage: $0 <bat-git-hash>\"\n    exit 1\nfi\n\nscript_path=$(real"
  },
  {
    "path": "bat/verify.sh",
    "chars": 680,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nscript_path=$(realpath \"$0\")\nscript_dir=$(dirname \"$script_path\")\nclone_path=$(mktemp -d)\n\n"
  },
  {
    "path": "build.rs",
    "chars": 1580,
    "preview": "use std::{\n    env,\n    fs::{self, File},\n    io::{self, BufWriter, Write},\n};\n\n// Take all files under `themes` and tur"
  },
  {
    "path": "config-file-schema.json",
    "chars": 29382,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"Config\",\n  \"type\": \"object\",\n  \"properties\": {\n   "
  },
  {
    "path": "config.sample.yaml",
    "chars": 3039,
    "preview": "---\n# yaml-language-server: $schema=https://raw.githubusercontent.com/mfontanini/presenterm/master/config-file-schema.js"
  },
  {
    "path": "docs/.gitignore",
    "chars": 6,
    "preview": "book/\n"
  },
  {
    "path": "docs/book.toml",
    "chars": 680,
    "preview": "[book]\nauthors = [\"mfontanini\"]\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\ntitle = \"presenterm documentation\"\n\n[pr"
  },
  {
    "path": "docs/src/SUMMARY.md",
    "chars": 976,
    "preview": "# Summary\n\n[Introduction](./introduction.md)\n\n# Docs\n\n- [Install](./install.md)\n- [Features](./features/introduction.md)"
  },
  {
    "path": "docs/src/acknowledgements.md",
    "chars": 1028,
    "preview": "## Acknowledgements\n\nThis tool is heavily inspired by:\n\n* [slides][slides_url]\n* [lookatme][lookatme_url]\n* [sli.dev][sl"
  },
  {
    "path": "docs/src/configuration/introduction.md",
    "chars": 1438,
    "preview": "# Configuration\n\n_presenterm_ allows you to customize its behavior via a configuration file. This file is stored, along "
  },
  {
    "path": "docs/src/configuration/options.md",
    "chars": 4818,
    "preview": "# Options\n\nOptions are special configuration parameters that can be set either in the configuration file under the `opti"
  },
  {
    "path": "docs/src/configuration/settings.md",
    "chars": 12410,
    "preview": "# Settings\n\nAs opposed to options, the rest of these settings **can only be configured via the configuration file**.\n\n##"
  },
  {
    "path": "docs/src/features/code/d2.md",
    "chars": 916,
    "preview": "# D2\n\n[D2](https://d2lang.com/) snippets can be converted into images automatically for any snippets tagged with the `d2"
  },
  {
    "path": "docs/src/features/code/execution.md",
    "chars": 9425,
    "preview": "# Snippet execution\n\n## Executing code blocks\n\nAnnotating a code block with a `+exec` attribute will make it executable."
  },
  {
    "path": "docs/src/features/code/highlighting.md",
    "chars": 6308,
    "preview": "# Code highlighting\n\nCode highlighting is supported for the following languages:\n\n| Language   | Execution support |\n|--"
  },
  {
    "path": "docs/src/features/code/latex.md",
    "chars": 3048,
    "preview": "# LaTeX and typst\n\n`latex` and `typst` code blocks can be marked with the `+render` attribute (see [highlighting](highli"
  },
  {
    "path": "docs/src/features/code/mermaid.md",
    "chars": 2082,
    "preview": "## Mermaid\n\n[mermaid](https://mermaid.js.org/) snippets can be converted into images automatically in any code snippet t"
  },
  {
    "path": "docs/src/features/commands.md",
    "chars": 6227,
    "preview": "# Comment commands\n\n_presenterm_ uses \"comment commands\" in the form of HTML comments to let the user specify certain be"
  },
  {
    "path": "docs/src/features/exports.md",
    "chars": 1936,
    "preview": "# Exporting presentations\n\nPresentations can be exported to PDF and HTML, to allow easily sharing the slide deck at the "
  },
  {
    "path": "docs/src/features/images.md",
    "chars": 2359,
    "preview": "# Images\n\nImages are supported and will render in your terminal as long as it supports either the [iterm2 image \nprotoco"
  },
  {
    "path": "docs/src/features/introduction.md",
    "chars": 7018,
    "preview": "# Introduction\n\nThis guide teaches you how to use _presenterm_. At this point you should have already installed _present"
  },
  {
    "path": "docs/src/features/layout.md",
    "chars": 3339,
    "preview": "# Layouts\n\n_presenterm_ currently supports a column layout that lets you split parts of your slides into column. This al"
  },
  {
    "path": "docs/src/features/slide-transitions.md",
    "chars": 879,
    "preview": "# Slide transitions\n\nSlide transitions allow animating your presentation every time you move from a slide to the next/pr"
  },
  {
    "path": "docs/src/features/speaker-notes.md",
    "chars": 2383,
    "preview": "## Speaker notes\n\nStarting on version 0.10.0, _presenterm_ allows presentations to define speaker notes. The way this wo"
  },
  {
    "path": "docs/src/features/themes/definition.md",
    "chars": 12154,
    "preview": "# Theme definition\n\nThis section goes through the structure of the theme files. Have a look at some of the [existing \nth"
  },
  {
    "path": "docs/src/features/themes/introduction.md",
    "chars": 3982,
    "preview": "# Themes\n\n_presenterm_ tries to be as configurable as possible, allowing users to create presentations that look exactly"
  },
  {
    "path": "docs/src/install.md",
    "chars": 3071,
    "preview": "# Installing _presenterm_\n\n_presenterm_ works on Linux, macOS, and Windows and can be installed in different ways:\n\n####"
  },
  {
    "path": "docs/src/internals/parse.md",
    "chars": 4647,
    "preview": "# Parsing and rendering\n\nThis document goes through the internals of how we take a markdown file and finish rendering it"
  },
  {
    "path": "docs/src/introduction.md",
    "chars": 689,
    "preview": "# presenterm\n\n[presenterm][github] lets you create presentations in markdown format and run them from your terminal, wit"
  },
  {
    "path": "examples/README.md",
    "chars": 2345,
    "preview": "Examples\n===\n\nThis section contains a few example presentations that display different features and styles you can use i"
  },
  {
    "path": "examples/code.md",
    "chars": 1756,
    "preview": "---\ntheme:\n  override:\n    code:\n      alignment: left\n      background: false\n---\n\nCode styling\n===\n\nThis presentation "
  },
  {
    "path": "examples/columns.md",
    "chars": 371,
    "preview": "# Columns and pauses\n\nColumns and pauses can interact with each other in useful ways:\n\n<!-- pause -->\n\n<!-- column_layou"
  },
  {
    "path": "examples/custom-intro-slides.md",
    "chars": 661,
    "preview": "<!-- newlines: 6 -->\n\n![](doge.png)\n\n\nCustom introduction slides\n====\n\n<!-- alignment: center -->\n\n<span style=\"color: b"
  },
  {
    "path": "examples/demo.md",
    "chars": 3404,
    "preview": "---\ntitle: Introducing _presenterm_\nauthor: Matias\n---\n\nCustomizability\n---\n_presenterm_ allows configuring almost anyth"
  },
  {
    "path": "examples/footer.md",
    "chars": 461,
    "preview": "---\ntheme:\n  override:\n    footer:\n      style: template\n      left:\n        image: doge.png\n      center: '**Introducti"
  },
  {
    "path": "examples/speaker-notes.md",
    "chars": 1247,
    "preview": "Speaker Notes\n===\n\n`presenterm` supports speaker notes.\n\nYou can use the following HTML comment throughout your presenta"
  },
  {
    "path": "executors.yaml",
    "chars": 5655,
    "preview": "---\nbash:\n  filename: script.sh\n  commands:\n    - [\"bash\", \"$pwd/script.sh\"]\n  hidden_line_prefix: \"/// \"\nc++:\n  filenam"
  },
  {
    "path": "flake.nix",
    "chars": 1530,
    "preview": "{\n  description = \"A terminal slideshow tool\";\n\n  inputs = {\n    flakebox = {\n      url = \"github:rustshop/flakebox?rev="
  },
  {
    "path": "rustfmt.toml",
    "chars": 142,
    "preview": "version = \"Two\"\nunstable_features = true\nuse_small_heuristics = \"Max\"\nmax_width = 120\nimports_granularity = \"Crate\"\nnorm"
  },
  {
    "path": "scripts/generate-config-file-schema.sh",
    "chars": 383,
    "preview": "#!/bin/bash\n\nset -euo pipefail\n\nscript_dir=$(dirname \"$0\")\nroot_dir=\"${script_dir}/../\"\n\ncurrent_schema=$(mktemp)\ndocker"
  },
  {
    "path": "scripts/parse-changelog.sh",
    "chars": 621,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nscript_dir=$(dirname \"$0\")\nroot_dir=\"${script_dir}/../\"\n\nif [ $# -ne 1 ]; then\n    echo \"Us"
  },
  {
    "path": "scripts/test-pdf-generation.sh",
    "chars": 631,
    "preview": "#!/bin/bash\n\nset -e\n\nscript_dir=$(dirname \"$0\")\nroot_dir=$(realpath \"${script_dir}/../\")\n\necho \"Creating python env\"\nenv"
  },
  {
    "path": "scripts/validate-config-file-schema.sh",
    "chars": 433,
    "preview": "#!/bin/bash\n\nset -euo pipefail\n\nscript_dir=$(dirname \"$0\")\nroot_dir=\"${script_dir}/../\"\n\ncurrent_schema=$(mktemp)\ncargo "
  },
  {
    "path": "src/code/execute.rs",
    "chars": 17079,
    "preview": "//! Code execution.\n\nuse super::snippet::SnippetExecutorSpec;\nuse crate::{\n    code::snippet::{Snippet, SnippetExecution"
  },
  {
    "path": "src/code/highlighting.rs",
    "chars": 10845,
    "preview": "use crate::{\n    code::snippet::SnippetLanguage,\n    markdown::{\n        elements::{Line, Text},\n        text_style::{Co"
  },
  {
    "path": "src/code/mod.rs",
    "chars": 101,
    "preview": "pub(crate) mod execute;\npub(crate) mod highlighting;\npub(crate) mod padding;\npub(crate) mod snippet;\n"
  },
  {
    "path": "src/code/padding.rs",
    "chars": 1273,
    "preview": "use std::iter;\n\npub(crate) struct NumberPadder {\n    width: usize,\n}\n\nimpl NumberPadder {\n    pub(crate) fn new(upper_bo"
  },
  {
    "path": "src/code/snippet.rs",
    "chars": 36763,
    "preview": "use super::{\n    highlighting::{LanguageHighlighter, StyledTokens},\n    padding::NumberPadder,\n};\nuse crate::{\n    markd"
  },
  {
    "path": "src/commands/keyboard.rs",
    "chars": 24090,
    "preview": "use super::listener::{Command, CommandDiscriminants};\nuse crate::config::KeyBindingsConfig;\nuse crossterm::event::{Event"
  },
  {
    "path": "src/commands/listener.rs",
    "chars": 3200,
    "preview": "use super::{\n    keyboard::{CommandKeyBindings, KeyBindingsValidationError, KeyboardListener},\n    speaker_notes::{Speak"
  },
  {
    "path": "src/commands/mod.rs",
    "chars": 80,
    "preview": "pub(crate) mod keyboard;\npub(crate) mod listener;\npub(crate) mod speaker_notes;\n"
  },
  {
    "path": "src/commands/speaker_notes.rs",
    "chars": 4164,
    "preview": "use serde::{Deserialize, Serialize};\nuse socket2::{Domain, Protocol, Socket, Type};\nuse std::{\n    io,\n    net::{SocketA"
  },
  {
    "path": "src/config.rs",
    "chars": 25567,
    "preview": "use crate::{\n    code::snippet::SnippetLanguage,\n    commands::keyboard::KeyBinding,\n    terminal::{GraphicsMode, emulat"
  },
  {
    "path": "src/demo.rs",
    "chars": 4767,
    "preview": "use crate::{\n    ImageRegistry, MarkdownParser, PresentationBuilderOptions, Resources, ThemeOptions, Themes, ThirdPartyR"
  },
  {
    "path": "src/export/exporter.rs",
    "chars": 11889,
    "preview": "use crate::{\n    MarkdownParser, Resources,\n    code::execute::SnippetExecutor,\n    config::{KeyBindingsConfig, PauseExp"
  },
  {
    "path": "src/export/html.rs",
    "chars": 4905,
    "preview": "use crate::markdown::text_style::{Color, TextAttribute, TextStyle};\nuse std::{borrow::Cow, fmt};\n\npub(crate) enum HtmlTe"
  },
  {
    "path": "src/export/mod.rs",
    "chars": 62,
    "preview": "pub mod exporter;\npub(crate) mod html;\npub(crate) mod output;\n"
  },
  {
    "path": "src/export/output.rs",
    "chars": 9448,
    "preview": "use super::{\n    exporter::{ExportError, OutputDirectory},\n    html::{FontSize, color_to_html},\n};\nuse crate::{\n    conf"
  },
  {
    "path": "src/export/script.js",
    "chars": 1248,
    "preview": "document.addEventListener('DOMContentLoaded', function() {\n  const allLines = document.querySelectorAll('body > div');\n "
  },
  {
    "path": "src/main.rs",
    "chars": 20248,
    "preview": "use crate::{\n    code::{execute::SnippetExecutor, highlighting::HighlightThemeSet},\n    commands::listener::CommandListe"
  },
  {
    "path": "src/markdown/elements.rs",
    "chars": 7537,
    "preview": "use super::text_style::{Color, TextStyle, UndefinedPaletteColorError};\nuse crate::theme::{ColorPalette, raw::RawColor};\n"
  },
  {
    "path": "src/markdown/html.rs",
    "chars": 7450,
    "preview": "use super::text_style::{Color, TextStyle};\nuse crate::theme::raw::{ParseColorError, RawColor};\nuse std::{borrow::Cow, st"
  },
  {
    "path": "src/markdown/mod.rs",
    "chars": 116,
    "preview": "pub(crate) mod elements;\npub(crate) mod html;\npub(crate) mod parse;\npub(crate) mod text;\npub(crate) mod text_style;\n"
  },
  {
    "path": "src/markdown/parse.rs",
    "chars": 44313,
    "preview": "use super::{\n    elements::{Line, ListItem, ListItemType, MarkdownElement, SourcePosition, Table, TableRow, Text},\n    h"
  },
  {
    "path": "src/markdown/text.rs",
    "chars": 14946,
    "preview": "use super::{\n    elements::{Line, Text},\n    text_style::TextStyle,\n};\nuse std::{fmt, mem};\nuse unicode_width::{UnicodeW"
  },
  {
    "path": "src/markdown/text_style.rs",
    "chars": 16016,
    "preview": "use crate::{\n    terminal::capabilities::TerminalCapabilities,\n    theme::{ColorPalette, raw::RawColor},\n};\nuse crosster"
  },
  {
    "path": "src/presentation/builder/comment.rs",
    "chars": 26392,
    "preview": "use crate::{\n    markdown::elements::{MarkdownElement, SourcePosition},\n    presentation::builder::{BuildResult, LayoutS"
  },
  {
    "path": "src/presentation/builder/error.rs",
    "chars": 8664,
    "preview": "use crate::{\n    code::execute::UnsupportedExecution,\n    markdown::{\n        elements::SourcePosition,\n        parse::P"
  },
  {
    "path": "src/presentation/builder/frontmatter.rs",
    "chars": 10586,
    "preview": "use crate::{\n    config::OptionsConfig,\n    markdown::{\n        elements::{Line, Text},\n        parse::MarkdownParser,\n "
  },
  {
    "path": "src/presentation/builder/heading.rs",
    "chars": 7671,
    "preview": "use crate::{\n    markdown::elements::{Line, Text},\n    presentation::builder::{BuildResult, LastElement, PresentationBui"
  },
  {
    "path": "src/presentation/builder/images.rs",
    "chars": 4281,
    "preview": "use crate::{\n    markdown::elements::{Percent, PercentParseError, SourcePosition},\n    presentation::builder::{\n        "
  },
  {
    "path": "src/presentation/builder/list.rs",
    "chars": 12912,
    "preview": "use crate::{\n    markdown::{\n        elements::{ListItem, ListItemType, Text},\n        text_style::TextStyle,\n    },\n   "
  },
  {
    "path": "src/presentation/builder/mod.rs",
    "chars": 32566,
    "preview": "use crate::{\n    code::{\n        execute::SnippetExecutor,\n        highlighting::{HighlightThemeSet, SnippetHighlighter}"
  },
  {
    "path": "src/presentation/builder/quote.rs",
    "chars": 5485,
    "preview": "use crate::{\n    markdown::{\n        elements::{Line, Text},\n        text_style::{Colors, TextStyle},\n    },\n    present"
  },
  {
    "path": "src/presentation/builder/snippet.rs",
    "chars": 33141,
    "preview": "use super::{BuildError, BuildResult};\nuse crate::{\n    code::{\n        execute::LanguageSnippetExecutor,\n        snippet"
  },
  {
    "path": "src/presentation/builder/sources.rs",
    "chars": 2452,
    "preview": "use crate::{markdown::elements::SourcePosition, presentation::builder::error::FileSourcePosition};\nuse std::{cell::RefCe"
  },
  {
    "path": "src/presentation/builder/table.rs",
    "chars": 3293,
    "preview": "use crate::{\n    markdown::elements::{Line, Table, TableRow, Text},\n    presentation::builder::{BuildResult, Presentatio"
  },
  {
    "path": "src/presentation/builder/tests.rs",
    "chars": 2514,
    "preview": "use super::*;\nuse crate::presentation::builder::utils::Test;\n\n#[test]\nfn prelude_appears_once() {\n    let input = \"---\na"
  },
  {
    "path": "src/presentation/diff.rs",
    "chars": 12544,
    "preview": "use crate::presentation::{Presentation, RenderOperation, SlideChunk};\nuse std::{any::Any, cmp::Ordering, fmt::Debug, mem"
  },
  {
    "path": "src/presentation/mod.rs",
    "chars": 19215,
    "preview": "use crate::{config::OptionsConfig, render::operation::RenderOperation};\nuse serde::Deserialize;\nuse std::{\n    cell::Ref"
  },
  {
    "path": "src/presentation/poller.rs",
    "chars": 3938,
    "preview": "use crate::render::operation::{Pollable, PollableState};\nuse std::{\n    sync::mpsc::{Receiver, RecvTimeoutError, Sender,"
  },
  {
    "path": "src/presenter.rs",
    "chars": 27329,
    "preview": "use crate::{\n    code::execute::SnippetExecutor,\n    commands::{\n        listener::{Command, CommandListener},\n        s"
  },
  {
    "path": "src/render/ascii_scaler.rs",
    "chars": 3412,
    "preview": "use super::{\n    RenderError,\n    engine::{RenderEngine, RenderEngineOptions},\n};\nuse crate::{\n    WindowSize,\n    prese"
  },
  {
    "path": "src/render/engine.rs",
    "chars": 39639,
    "preview": "use super::{\n    RenderError, RenderResult, layout::Layout, operation::ImagePosition, properties::CursorPosition, text::"
  },
  {
    "path": "src/render/layout.rs",
    "chars": 6678,
    "preview": "use crate::{render::properties::WindowSize, theme::Alignment};\n\n#[derive(Debug)]\npub(crate) struct Layout {\n    alignmen"
  },
  {
    "path": "src/render/mod.rs",
    "chars": 5613,
    "preview": "pub(crate) mod ascii_scaler;\npub(crate) mod engine;\npub(crate) mod layout;\npub(crate) mod operation;\npub(crate) mod prop"
  },
  {
    "path": "src/render/operation.rs",
    "chars": 6665,
    "preview": "use super::properties::WindowSize;\nuse crate::{\n    markdown::{\n        text::{WeightedLine, WeightedText},\n        text"
  },
  {
    "path": "src/render/properties.rs",
    "chars": 4294,
    "preview": "use crossterm::terminal;\nuse std::io::{self, ErrorKind};\n\n/// The size of the terminal window.\n///\n/// This is the same "
  },
  {
    "path": "src/render/text.rs",
    "chars": 14114,
    "preview": "use crate::{\n    markdown::{\n        elements::Text,\n        text::{WeightedLine, WeightedText},\n        text_style::{Co"
  },
  {
    "path": "src/render/validate.rs",
    "chars": 1730,
    "preview": "use super::properties::WindowSize;\nuse crate::{\n    ImagePrinter,\n    presentation::Presentation,\n    render::{\n        "
  },
  {
    "path": "src/resource.rs",
    "chars": 8549,
    "preview": "use crate::{\n    terminal::image::{\n        Image,\n        printer::{ImageRegistry, ImageSpec, RegisterImageError},\n    "
  },
  {
    "path": "src/terminal/ansi.rs",
    "chars": 8030,
    "preview": "use crate::markdown::{\n    elements::{Line, Text},\n    text_style::{Color, TextStyle},\n};\nuse std::mem;\nuse vte::{Params"
  },
  {
    "path": "src/terminal/capabilities.rs",
    "chars": 10928,
    "preview": "use super::image::protocols::kitty::{Action, ControlCommand, ControlOption, ImageFormat, TransmissionMedium};\nuse base64"
  },
  {
    "path": "src/terminal/emulator.rs",
    "chars": 4609,
    "preview": "use super::{GraphicsMode, capabilities::TerminalCapabilities, image::protocols::kitty::KittyMode};\nuse std::{env, sync::"
  },
  {
    "path": "src/terminal/image/mod.rs",
    "chars": 2164,
    "preview": "use self::printer::{ImageProperties, TerminalImage};\nuse image::DynamicImage;\nuse protocols::ascii::AsciiImage;\nuse std:"
  },
  {
    "path": "src/terminal/image/printer.rs",
    "chars": 7960,
    "preview": "use super::{\n    Image, ImageSource,\n    protocols::{\n        ascii::{AsciiImage, AsciiPrinter},\n        iterm::{ItermIm"
  },
  {
    "path": "src/terminal/image/protocols/ascii.rs",
    "chars": 5643,
    "preview": "use crate::{\n    markdown::text_style::{Color, Colors, TextStyle},\n    terminal::{\n        image::printer::{ImagePropert"
  },
  {
    "path": "src/terminal/image/protocols/iterm.rs",
    "chars": 3916,
    "preview": "use crate::terminal::{\n    image::printer::{ImageProperties, ImageSpec, PrintImage, PrintImageError, PrintOptions, Regis"
  },
  {
    "path": "src/terminal/image/protocols/kitty.rs",
    "chars": 19886,
    "preview": "use crate::{\n    markdown::text_style::{Color, TextStyle},\n    terminal::{\n        image::printer::{ImageProperties, Ima"
  },
  {
    "path": "src/terminal/image/protocols/mod.rs",
    "chars": 108,
    "preview": "pub(crate) mod ascii;\npub(crate) mod iterm;\npub(crate) mod kitty;\npub(crate) mod raw;\npub(crate) mod sixel;\n"
  },
  {
    "path": "src/terminal/image/protocols/raw.rs",
    "chars": 2040,
    "preview": "use crate::terminal::{\n    image::printer::{ImageProperties, ImageSpec, PrintImage, PrintImageError, PrintOptions, Regis"
  },
  {
    "path": "src/terminal/image/protocols/sixel.rs",
    "chars": 2216,
    "preview": "use crate::terminal::{\n    image::printer::{\n        CreatePrinterError, ImageProperties, ImageSpec, PrintImage, PrintIm"
  },
  {
    "path": "src/terminal/image/scale.rs",
    "chars": 4731,
    "preview": "use crate::render::properties::{CursorPosition, WindowSize};\n\npub(crate) trait ScaleImage {\n    /// Scale an image to a "
  },
  {
    "path": "src/terminal/mod.rs",
    "chars": 391,
    "preview": "pub(crate) mod ansi;\npub(crate) mod capabilities;\npub(crate) mod emulator;\npub(crate) mod image;\npub(crate) mod printer;"
  },
  {
    "path": "src/terminal/printer.rs",
    "chars": 8919,
    "preview": "use super::emulator::TerminalEmulator;\nuse crate::{\n    markdown::text_style::{Color, Colors, TextStyle},\n    terminal::"
  },
  {
    "path": "src/terminal/virt.rs",
    "chars": 10331,
    "preview": "use super::{\n    image::{\n        Image,\n        printer::{PrintImage, PrintImageError, PrintOptions},\n        protocols"
  },
  {
    "path": "src/theme/clean.rs",
    "chars": 30074,
    "preview": "use super::{\n    AuthorPositioning, FooterTemplate, Margin,\n    raw::{self, RawColor},\n};\nuse crate::{\n    markdown::tex"
  },
  {
    "path": "src/theme/mod.rs",
    "chars": 179,
    "preview": "pub(crate) mod clean;\npub(crate) mod raw;\npub(crate) mod registry;\n\npub(crate) use clean::*;\npub(crate) use raw::{Author"
  },
  {
    "path": "src/theme/raw.rs",
    "chars": 32669,
    "preview": "use super::registry::LoadThemeError;\nuse crate::markdown::text_style::{Color, Colors, UndefinedPaletteColorError};\nuse h"
  },
  {
    "path": "src/theme/registry.rs",
    "chars": 9544,
    "preview": "use super::raw::PresentationTheme;\nuse std::{\n    collections::BTreeMap,\n    fs, io,\n    path::{Path, PathBuf},\n};\n\nincl"
  },
  {
    "path": "src/third_party.rs",
    "chars": 14490,
    "preview": "use crate::{\n    ImageRegistry,\n    config::{default_mermaid_scale, default_snippet_render_threads, default_typst_ppi},\n"
  },
  {
    "path": "src/tools.rs",
    "chars": 3756,
    "preview": "use itertools::Itertools;\nuse std::{\n    io::{self, Write},\n    process::{Command, Output, Stdio},\n};\n\nconst DEFAULT_MAX"
  },
  {
    "path": "src/transitions/collapse_horizontal.rs",
    "chars": 2249,
    "preview": "use super::{AnimateTransition, LinesFrame, TransitionDirection};\nuse crate::terminal::virt::TerminalGrid;\n\npub(crate) st"
  },
  {
    "path": "src/transitions/fade.rs",
    "chars": 4799,
    "preview": "use super::{AnimateTransition, AnimationFrame, TransitionDirection};\nuse crate::{\n    markdown::text_style::TextStyle,\n "
  },
  {
    "path": "src/transitions/mod.rs",
    "chars": 5091,
    "preview": "use crate::{\n    markdown::{elements::Line, text_style::Color},\n    terminal::{\n        printer::TerminalCommand,\n      "
  },
  {
    "path": "src/transitions/slide_horizontal.rs",
    "chars": 3754,
    "preview": "use super::{AnimateTransition, LinesFrame, TransitionDirection};\nuse crate::{\n    WindowSize,\n    markdown::elements::Li"
  },
  {
    "path": "src/ui/execution/acquire_terminal.rs",
    "chars": 4677,
    "preview": "use crate::{\n    code::{execute::LanguageSnippetExecutor, snippet::Snippet},\n    markdown::elements::{Line, Text},\n    r"
  },
  {
    "path": "src/ui/execution/disabled.rs",
    "chars": 1939,
    "preview": "use crate::{\n    markdown::{elements::Text, text_style::TextStyle},\n    render::{\n        operation::{AsRenderOperations"
  },
  {
    "path": "src/ui/execution/image.rs",
    "chars": 5017,
    "preview": "use crate::{\n    code::{\n        execute::{ExecutionHandle, LanguageSnippetExecutor, ProcessStatus},\n        snippet::Sn"
  },
  {
    "path": "src/ui/execution/mod.rs",
    "chars": 356,
    "preview": "pub(crate) mod acquire_terminal;\npub(crate) mod disabled;\npub(crate) mod image;\npub(crate) mod output;\npub(crate) mod pt"
  },
  {
    "path": "src/ui/execution/output.rs",
    "chars": 12749,
    "preview": "use crate::{\n    code::{\n        execute::{ExecutionHandle, ExecutionState, LanguageSnippetExecutor, ProcessStatus},\n   "
  },
  {
    "path": "src/ui/execution/pty.rs",
    "chars": 13974,
    "preview": "use crate::{\n    code::{\n        execute::{LanguageSnippetExecutor, ProcessStatus, PtySnippetContext},\n        snippet::"
  },
  {
    "path": "src/ui/execution/validator.rs",
    "chars": 6490,
    "preview": "use crate::{\n    code::{\n        execute::{ExecutionHandle, LanguageSnippetExecutor, ProcessStatus},\n        snippet::{E"
  },
  {
    "path": "src/ui/footer.rs",
    "chars": 13632,
    "preview": "use crate::{\n    markdown::{\n        elements::{Line, Text},\n        parse::{MarkdownParser, ParseInlinesError},\n       "
  },
  {
    "path": "src/ui/mod.rs",
    "chars": 98,
    "preview": "pub(crate) mod execution;\npub(crate) mod footer;\npub(crate) mod modals;\npub(crate) mod separator;\n"
  },
  {
    "path": "src/ui/modals.rs",
    "chars": 11500,
    "preview": "use crate::{\n    code::padding::NumberPadder,\n    commands::keyboard::KeyBinding,\n    config::KeyBindingsConfig,\n    mar"
  },
  {
    "path": "src/ui/separator.rs",
    "chars": 2887,
    "preview": "use crate::{\n    markdown::{\n        elements::{Line, Text},\n        text_style::TextStyle,\n    },\n    render::{\n       "
  },
  {
    "path": "src/utils.rs",
    "chars": 1955,
    "preview": "use serde::{Deserializer, Serializer};\nuse std::{\n    fmt::{self, Display},\n    marker::PhantomData,\n    str::FromStr,\n}"
  },
  {
    "path": "themes/catppuccin-frappe.yaml",
    "chars": 3292,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: palette:text\n    background: palette:base\n\ncolumn_layout"
  },
  {
    "path": "themes/catppuccin-latte.yaml",
    "chars": 3282,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: palette:text\n    background: palette:base\n\ncolumn_layout"
  },
  {
    "path": "themes/catppuccin-macchiato.yaml",
    "chars": 3292,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: palette:text\n    background: palette:base\n\ncolumn_layout"
  },
  {
    "path": "themes/catppuccin-mocha.yaml",
    "chars": 3292,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: palette:text\n    background: palette:base\n\ncolumn_layout"
  },
  {
    "path": "themes/dark.yaml",
    "chars": 3048,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: palette:white\n    background: \"040312\"\n\ncolumn_layout:\n "
  },
  {
    "path": "themes/gruvbox-dark.yaml",
    "chars": 2508,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: \"ebdbb2\"\n    background: \"282828\"\n\ncolumn_layout:\n  marg"
  },
  {
    "path": "themes/light.yaml",
    "chars": 2519,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: \"212529\"\n    background: \"f8f9fa\"\n\ncolumn_layout:\n  marg"
  },
  {
    "path": "themes/terminal-dark.yaml",
    "chars": 2338,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: null\n    background: null\n\ncolumn_layout:\n  margin:\n    "
  },
  {
    "path": "themes/terminal-light.yaml",
    "chars": 2439,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: null\n    background: null\n\ncolumn_layout:\n  margin:\n    "
  },
  {
    "path": "themes/tokyonight-day.yaml",
    "chars": 2518,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: \"3760bf\"\n    background: \"e1e2e7\"\n\ncolumn_layout:\n  marg"
  },
  {
    "path": "themes/tokyonight-moon.yaml",
    "chars": 2532,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: \"c8d3f5\"\n    background: \"222436\"\n\ncolumn_layout:\n  marg"
  },
  {
    "path": "themes/tokyonight-night.yaml",
    "chars": 2532,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: \"c0caf5\"\n    background: \"1a1b26\"\n\ncolumn_layout:\n  marg"
  },
  {
    "path": "themes/tokyonight-storm.yaml",
    "chars": 2532,
    "preview": "---\ndefault:\n  margin:\n    percent: 8\n  colors:\n    foreground: \"c0caf5\"\n    background: \"24283b\"\n\ncolumn_layout:\n  marg"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the mfontanini/presenterm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 155 files (1.1 MB), approximately 263.3k tokens, and a symbol index with 1794 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!