Skip to main content

Generate beautiful images of code with syntax highlighting in a stylish terminal window.

Project description

PyCheese

GitHub release PyPI version Codecov License codecov

PyCheese is a Python-based tool for generating beautiful, high-quality images of code with syntax highlighting, rendered in a macOS-style terminal window. Built for automation and easy customization, it can be easily integrated into scripts or pipelines.

example-image


Features

  • Syntax Highlighting – Utilizes Pygments with support for dozens of languages.
  • macOS-style Terminal UI – Recreates the terminal header and shadow.
  • Fonts – Use any TTF font, comes with JetBrains Mono for elegant, readable code.
  • Fully Scriptable – Designed to run headlessly from scripts, CI pipelines, or other Python apps.
  • Easily Customizable – Modify themes, fonts, window styles, and more in plain Python.
  • Self-contained – No need for browsers or servers. Everything runs locally.

Installation

pip install pycheese

Test if the tool works by running the following and looking at the output PNG file.

echo "import os" | pycheese

Command Line Usage

Render the code in sample_code.py in a default 80x24 window. By default, the window scrolls with the code and only the last 24 rows will be shown if the code does not fit into the window.

pycheese --file tests/sample_code.py

Use the --columns and --rows options to change the window size.

pycheese --columns 45 --file tests/sample_code.py

Set the --style to dracula and save the output to window.png.

pycheese --columns 80 --rows 24 --style dracula \
         --file tests/sample_code.py --output window.png

Docker

It's also possible to run the application in an isolated container. First, the Docker image needs to be built.

docker build -t pycheese-app .

Then the application can be run easily from within the container.

docker run --rm pycheese-app --help

Mount the local directory to allow the docker container to read Python files and output images.

docker run -v $(pwd):/data --rm pycheese-app --columns 45 --file code.py --output out.png

Programmatic Usage

The Python API allows more fine-grained control over the end-result by setting the appropiate parameters of the RenderConfig().

from pycheese import *

config = RenderConfig()
render = Render(config)

code = 'print("Hello, world!")'
render.render(code=code)
render.save_image("hello_world.png")

A slightly more custom way to call the tool is to create a RenderConfig to overwrite specific parameters.

config = RenderConfig(
    rows = 10,
    columns = 30,
    shadow_blur = 10,
    shadow_color = "darkblue",
    shadow_alpha = 80,
    shadow_offset = 40,
    margin = 50,
    first_bg_color = "#775588",
    second_bg_color = "#663355",
)
render = Render(config)

code = 'print("Hello, world!")'
render.render(code=code)
# show the PIL image object directly
render.final_image.show()

PyCheese renders four distinct layers: background, shadow, text, and title bar. They are composited into the final image. This approach allows the modification of individual layers for an animation without having to re-render any other layers. Each layer can be rendered separately (e.g. .render_text_layer()) and retrieved (e.g. .text_layer).

  • bg_layer
  • shadow_layer
  • text_layer
  • titlebar_layer
  • final_image

It's possible to efficiently generate multiple images or an animation by only modifying the layer that is changing. Here we change the style of the text layer, all the remaining layers remain unchanged and will not get re-rendered when .render() is called.

import time
code='print("Hello, world!")'

for style in ["monokai", "dracula"]:
    render.render_text_layer(code=code, style=style)
    render.render()
    render.final_image.show()
    time.sleep(0.5)

Fonts

The tool comes with the JetBrainsMono font. Support for custom fonts is experimental at this point.

To add more fonts, edit the font_config.toml file in the fonts/ directory. And download it with the included fonts-tool.

fonts-tool --update-font NewFont

Once added the font can be selected using its family name, the name excluding regular/bold/italic suffixes and the .ttf extension. The included font's family name is JetBrainsMono and the family name for the above example is "MesloLGS NF". Check quickly if the new font works by setting the --font option.

echo "import os" | pycheese --font "MesloLGS NF"

You can list all available fonts.

fonts-tool --list

And even add local fonts.

fonts-tool --add-local-font ~/Library/Fonts/MesloLGS\ NF\ Regular.ttf

Styles

PyCheese uses the Pygments library which comes with a range of styles that can be selected with the --style options. The complete list can be found here.

Dark Style Light Style
monokai solarized-light
zenburn gruvbox-light
nord friendly
dracula friendly_grayscale
gruvbox-dark murphy

Line Wrapping

Line wrapping is applied to fit content into the limits of the rendered terminal window. Currently, the line wrapping happens at character level and can break up words. To see it in action, run the linewrap.py script directly.

hatch run python src/pycheese/utils/linewrap.py --columns 20 tests/sample_code.py

Alternatives

PyCheese is by far not the only way to produce beautiful images of code. (However, it is one of few that can be easily run locally and used for automation.) Here is a small selection of alternatives:

Font License

JetBrains Mono typeface is available under the OFL-1.1 License and can be used free of charge, for both commercial and non-commercial purposes. You do not need to give credit to JetBrains, although we will appreciate it very much if you do. See JetBrainsMono License

License

With the exception of the font files, the code and assets contained in this repository are licensed under GNU General Public License v3.0 as detailed in the LICENSE file.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pycheese-0.3.0.tar.gz (641.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pycheese-0.3.0-py3-none-any.whl (567.5 kB view details)

Uploaded Python 3

File details

Details for the file pycheese-0.3.0.tar.gz.

File metadata

  • Download URL: pycheese-0.3.0.tar.gz
  • Upload date:
  • Size: 641.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for pycheese-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3ccf68ab6eac20ee4dfbbb3c4d422e7534f0f1a658920e6fc07eb31ae1611329
MD5 023ee3748f05e701459d29a919f66e31
BLAKE2b-256 700c63a522c4345b409b162f249555736686976d2f22bf23b8639cabdb7f6b93

See more details on using hashes here.

File details

Details for the file pycheese-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pycheese-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 567.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for pycheese-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 952ecb06dff249be500dd925b14fc0debe4635ad603325474bb0e214553ab842
MD5 ca5b8a10d7a986d8b8a840e47df7f7e4
BLAKE2b-256 33a0e76cb0d53460681d36d51806b5802bec56257550e4aaa3104df34349923d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page