https://github.com/sindrets/spt_gfx
Simple Python Terminal Graphics - A simple, lightweight framework for creating graphics in the terminal.
https://github.com/sindrets/spt_gfx
Last synced: 8 months ago
JSON representation
Simple Python Terminal Graphics - A simple, lightweight framework for creating graphics in the terminal.
- Host: GitHub
- URL: https://github.com/sindrets/spt_gfx
- Owner: sindrets
- Created: 2019-11-18T04:51:35.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2019-12-03T15:07:27.000Z (over 6 years ago)
- Last Synced: 2025-03-06T06:26:37.312Z (about 1 year ago)
- Language: Python
- Homepage:
- Size: 35.2 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Simple Python Terminal Graphics
`spt_gfx` is a small, lightweight framework that is designed to give you a simple, yet fast and powerful way to access the alternate buffer and create graphics in the terminal.
> Note: Only works with ANSI terminals. This framework heavily relies on ANSI control sequences, and I'm not really interested in supporting Windows.
### Installation
```sh
sudo python3 setup.py install
```
### Usage
Following is a simple example of how to draw some text to the screen and attach a key listener.
```python
from spt_gfx import Screen, KeyEvent
screen = Screen()
screen.open()
screen.setTextWrap(
10, 5,
"This text is written directly to the screen, and will disappear on"
+ "the next screen clear."
)
def screenUpdate(this: Screen):
this.setTextWrap(
10, 9,
"This text is written from the screen's update method, and will "
+ "persist over screen refreshes."
)
screen.update = screenUpdate
def onKeyPressed(keyEvent: KeyEvent):
screen.clear()
screen.setString(1, 1, str(keyEvent))
screen.refresh()
screen.addKeyListener(onKeyPressed)
screen.refresh()
```
The `screen.open()` method initializes the screen and opens the alternate buffer. You leave the alternate buffer and dispose of the screen by calling the `screen.close()` method. By default this method is called when pressing ctrl+c or ctrl+d, but this can be intercepted in a key listener by calling `keyEvent.invalidate()`.
The `screen.update` property is a callable that is a called on each screen refresh. This property exists on all `Buffer` objects.
The `screen.refresh()` method will first call every buffer's update method before rendering all pending draw events to the screen.
There are four methods for drawing text to the screen:
```python
buffer.setString(x: int, y: int, data: str)
```
This method is used for modifying a single line in the buffer, and does not support newline characters. When reaching the end of the screen it will simply stop.
```python
buffer.setText(x: int, y: int, data: str)
```
This method supports newline characters and new lines will start from the same x-value as the initial line.
```python
buffer.setTextWrap(x: int, y: int, data: str)
```
This method supports newline characters and will also automatically hard-wrap text that reaches the end of the screen.
```python
buffer.setTextWrapWords(x: int, y: int, data: str)
```
This is similar to the `setTextWrap` method, but this will sensibly wrap words.
### Using multiple Buffer objects
The following is an example of how to use multiple buffer objects. This example, along with the `lorem_ipsum.txt` file can be located in `./test`.
```python
from spt_gfx import Screen, Buffer, KeyEvent, color, Key
from pathlib import Path
screen = Screen()
screen.open()
styles = [
color.yellow.bold,
color.red.italic,
color.green.underline
]
currentStyleIndex = 0
currentStyle = styles[currentStyleIndex]
def cycleStyles():
global currentStyleIndex, styles, currentStyle
currentStyleIndex += 1
currentStyleIndex %= len(styles)
currentStyle = styles[currentStyleIndex]
lorem = ""
with open(Path(__file__).joinpath("../lorem_ipsum.txt").resolve(), "r") as file:
lorem = file.read()
content = Buffer()
def contentUpdate(this: Buffer):
this.clear()
this.setTextWrap(1, 1, currentStyle(lorem))
content.update = contentUpdate
content.setZ(1)
screen.addBuffer(content)
ui = Buffer()
def uiUpdate(this: Buffer):
this.clear()
this.setString(
1, this.getHeight(), color.bgWhite.black(
" enter: cycle styles ctrl+c: quit"
+ (" " * this.getWidth())
)
)
ui.update = uiUpdate
ui.setZ(2)
screen.addBuffer(ui)
def onKeyPressed(keyEvent: KeyEvent):
if Key.ENTER in keyEvent.keys:
cycleStyles()
screen.refresh()
screen.addKeyListener(onKeyPressed)
screen.refresh()
```
The `buffer.setZ()` method adjusts the buffer's z-index. The z-index determines the order in which the buffers are drawn to the screen. Buffers with higher z values are drawn over buffers with lower z values.
On screen refresh, the renderer merges the data from all buffers into a temporary buffer before all data is drawn to the screen in a single print call. This helps minimize any flashing that might occur if the buffers are drawn to the screen in sequence.
### Text styling
Included in the framework is a text styling utility that is heavily inspired by [chalk](https://github.com/chalk/chalk). The usage is simple:
```python
from spt_gfx import color
print(color.yellow("Foo bar."))
```
And just like chalk, the API calls are chainable:
```python
print(color.yellow.bgCyan.italic.underline("Foo bar."))
```
For terminals that support truecolor you can also use RGB:
```python
print(color.bgRgb(233, 30, 99)("Foo bar."))
```