Generate beautiful images of code with syntax highlighting in a stylish terminal window.
Project description
PyCheese
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.
Features
- Syntax Highlighting – Utilizes Pygments with support for dozens of languages.
- MacOS-Style Terminal UI – Recreates the terminal header and shadow.
- Fonts – Comes with JetBrains Mono for elegant, readable code. Use any TTF font.
- 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 connectivity and REST calls. Everything runs locally.
Installation & Quickstart
pip install pycheese
Run the following and look at the PNG file.
echo "import os" | pycheese
Usage
Command Line
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, build the Docker image.
docker build -t pycheese-app .
Then run the application container.
docker run --rm pycheese-app --help
Mount the local directory to allow Docker to read Python files and save image files.
docker run -v $(pwd):/data --rm pycheese-app --file code.py --output out.png
Python API
The Python API allows more fine-grained control over the end-result by setting the appropiate configuration parameters. First create a RenderConfig and then a Render object. Then call .render(code="import os") on the Render object and save the output with .save_image().
from pycheese import *
config = RenderConfig() # use defaults
render = Render(config)
code = 'print("Hello, world!")'
render.render(code=code)
render.save_image("hello_world.png")
Any parameters can be set via the RenderConfig. Defaults will be used for the remaining ones.
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()
Layers & Animations
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_layershadow_layertext_layertitlebar_layerfinal_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)
Styles
PyCheese uses the Pygments library which comes with a range of styles that can be selected with the --style options. The complete list with examples can be found here.
| Dark Style | Light Style |
|---|---|
| monokai | solarized-light |
| zenburn | gruvbox-light |
| nord | friendly |
| dracula | friendly_grayscale |
| gruvbox-dark | murphy |
Fonts
The tool comes with the JetBrainsMono font.
ℹ️ Note: Custom font support is experimental. It's recommended to use the default "JetBrainsMono".
To add more fonts, edit the font_config.toml file in the fonts/ directory. And download it with the included fonts-tool.
font-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.
font-tool --list
And even add local fonts.
font-tool --add-local-font ~/Library/Fonts/MesloLGS\ NF\ Regular.ttf
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 script directly.
linewrap --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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycheese-0.3.2.tar.gz.
File metadata
- Download URL: pycheese-0.3.2.tar.gz
- Upload date:
- Size: 643.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a45b4d901dda60d1c7a503bf35d50b69554700b3c7a96425f2322396e388a07
|
|
| MD5 |
76e86b92db194b53b0b9f245617c39ef
|
|
| BLAKE2b-256 |
ae40e134995ada254416a65936ace19b415818aa59ad91e19a7e423f89f7f29d
|
File details
Details for the file pycheese-0.3.2-py3-none-any.whl.
File metadata
- Download URL: pycheese-0.3.2-py3-none-any.whl
- Upload date:
- Size: 568.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1432c185905ffc973cf1375be499f70791269315930c9b0ef151259c7548f8e
|
|
| MD5 |
414d523eba8209ad739bb4ab36514a10
|
|
| BLAKE2b-256 |
da4e3702679fc85e0997c9d5562c2bac4058909e157fe9df2dedac24f3731dd1
|