Introduction
============
.. image:: https://readthedocs.org/projects/adafruit-circuitpython-dang/badge/?version=latest
:target: https://docs.circuitpython.org/projects/dang/en/latest/
:alt: Documentation Status
.. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg
:target: https://adafru.it/discord
:alt: Discord
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_Dang/workflows/Build%20CI/badge.svg
:target: https://github.com/adafruit/Adafruit_CircuitPython_Dang/actions
:alt: Build Status
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
:target: https://github.com/astral-sh/ruff
:alt: Code Style: Ruff
A subset of the curses framework. Used for making terminal based applications.
Dependencies
=============
This driver depends on:
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
Please ensure all dependencies are available on the CircuitPython filesystem.
This is easily achieved by downloading
`the Adafruit library and driver bundle <https://circuitpython.org/libraries>`_
or individual libraries can be installed using
`circup <https://github.com/adafruit/circup>`_.
Works with any displayio based display.
Installing from PyPI
=====================
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
PyPI <https://pypi.org/project/adafruit-circuitpython-dang/>`_.
To install for current user:
.. code-block:: shell
pip3 install adafruit-circuitpython-dang
To install system-wide (this may be required in some cases):
.. code-block:: shell
sudo pip3 install adafruit-circuitpython-dang
To install in a virtual environment in your current project:
.. code-block:: shell
mkdir project-name && cd project-name
python3 -m venv .venv
source .env/bin/activate
pip3 install adafruit-circuitpython-dang
Installing to a Connected CircuitPython Device with Circup
==========================================================
Make sure that you have ``circup`` installed in your Python environment.
Install it with the following command if necessary:
.. code-block:: shell
pip3 install circup
With ``circup`` installed and your CircuitPython device connected use the
following command to install:
.. code-block:: shell
circup install adafruit_dang
Or the following command to update an existing version:
.. code-block:: shell
circup update
Usage Example
=============
.. code-block:: python
import time
import supervisor
import terminalio
from displayio import Group, Palette, TileGrid
from terminalio import Terminal
import adafruit_dang as curses
class Window:
def __init__(self, n_rows, n_cols, row=0, col=0):
self.n_rows = n_rows
self.n_cols = n_cols
self.row = row
self.col = col
@property
def bottom(self):
return self.row + self.n_rows - 1
def up(self, cursor): # pylint: disable=invalid-name
if cursor.row == self.row - 1 and self.row > 0:
self.row -= 1
def down(self, buffer, cursor):
if cursor.row == self.bottom + 1 and self.bottom < len(buffer) - 1:
self.row += 1
def horizontal_scroll(self, cursor, left_margin=5, right_margin=2):
n_pages = cursor.col // (self.n_cols - right_margin)
self.col = max(n_pages * self.n_cols - right_margin - left_margin, 0)
def translate(self, cursor):
return cursor.row - self.row, cursor.col - self.col
def helloworld_main(stdscr, terminal_tilegrid):
window = Window(terminal_tilegrid.height, terminal_tilegrid.width)
stdscr.erase()
img = [None] * window.n_rows
user_input = ""
user_entered_message = ""
last_key_press = ""
def setline(row, line):
if img[row] == line:
return
img[row] = line
line += " " * (window.n_cols - len(line) - 1)
stdscr.addstr(row, 0, line)
while True:
header = "Hello World Adafruit Dang"
margin = (window.n_cols - 1 - len(header)) // 2
setline(1, f"{' ' * margin}{header}")
key_press_message = f"Last key pressed: {last_key_press}"
margin = (window.n_cols - 1 - len(key_press_message)) // 2
setline(4, f"{' ' * margin}{key_press_message}")
last_entered = f"Entered Message: {user_entered_message}"
margin = (window.n_cols - 1 - len(last_entered)) // 2
setline(6, f"{' ' * margin}{last_entered}")
user_input_row = window.n_rows - 2
if user_input:
setline(user_input_row, user_input)
else:
setline(user_input_row, " " * (window.n_cols - 1))
status_message_row = terminal_tilegrid.height - 1
status_message = f" Adafruit Dang | Demo | Fruit Jam | {int(time.monotonic())}"
status_message += " " * (window.n_cols - len(status_message) - 1)
line = f"{status_message}"
setline(status_message_row, line)
k = stdscr.getkey()
if k is not None:
if len(k) == 1 and " " <= k <= "~":
user_input += k
last_key_press = k
elif k == "\n":
user_entered_message = user_input
user_input = ""
elif k in {"KEY_BACKSPACE", "\x7f", "\x08"}:
user_input = user_input[:-1]
def run_helloworld_main(terminal, terminal_tilegrid):
return curses.custom_terminal_wrapper(terminal, helloworld_main, terminal_tilegrid)
main_group = Group()
display = supervisor.runtime.display
font = terminalio.FONT
char_size = font.get_bounding_box()
print(f"char_size: {char_size}")
screen_size = (display.width // char_size[0], display.height // char_size[1])
terminal_palette = Palette(2)
terminal_palette[0] = 0x000000
terminal_palette[1] = 0xFFFFFF
terminal_area = TileGrid(
bitmap=font.bitmap,
width=screen_size[0],
height=screen_size[1],
tile_width=char_size[0],
tile_height=char_size[1],
pixel_shader=terminal_palette,
)
main_group.append(terminal_area)
terminal = Terminal(terminal_area, font)
display.root_group = main_group
run_helloworld_main(terminal, terminal_area)
Documentation
=============
API documentation for this library can be found on `Read the Docs <https://docs.circuitpython.org/projects/dang/en/latest/>`_.
For information on building library documentation, please check out
`this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
Contributing
============
Contributions are welcome! Please read our `Code of Conduct
<https://github.com/adafruit/Adafruit_CircuitPython_Dang/blob/HEAD/CODE_OF_CONDUCT.md>`_
before contributing to help this project stay welcoming.
Raw data
{
"_id": null,
"home_page": null,
"name": "adafruit-circuitpython-dang",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "adafruit, blinka, circuitpython, micropython, dang, curses, terminal, ascii, ansi, tui",
"author": null,
"author_email": "Adafruit Industries <circuitpython@adafruit.com>",
"download_url": "https://files.pythonhosted.org/packages/ec/26/9f2041a8abf017fcffa7a12898a4e9e8c9fc96ef2309464305ed48d7c704/adafruit_circuitpython_dang-1.0.0.tar.gz",
"platform": null,
"description": "Introduction\n============\n\n\n.. image:: https://readthedocs.org/projects/adafruit-circuitpython-dang/badge/?version=latest\n :target: https://docs.circuitpython.org/projects/dang/en/latest/\n :alt: Documentation Status\n\n\n.. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg\n :target: https://adafru.it/discord\n :alt: Discord\n\n\n.. image:: https://github.com/adafruit/Adafruit_CircuitPython_Dang/workflows/Build%20CI/badge.svg\n :target: https://github.com/adafruit/Adafruit_CircuitPython_Dang/actions\n :alt: Build Status\n\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Code Style: Ruff\n\nA subset of the curses framework. Used for making terminal based applications.\n\n\nDependencies\n=============\nThis driver depends on:\n\n* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_\n\nPlease ensure all dependencies are available on the CircuitPython filesystem.\nThis is easily achieved by downloading\n`the Adafruit library and driver bundle <https://circuitpython.org/libraries>`_\nor individual libraries can be installed using\n`circup <https://github.com/adafruit/circup>`_.\n\n\nWorks with any displayio based display.\n\nInstalling from PyPI\n=====================\n\nOn supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from\nPyPI <https://pypi.org/project/adafruit-circuitpython-dang/>`_.\nTo install for current user:\n\n.. code-block:: shell\n\n pip3 install adafruit-circuitpython-dang\n\nTo install system-wide (this may be required in some cases):\n\n.. code-block:: shell\n\n sudo pip3 install adafruit-circuitpython-dang\n\nTo install in a virtual environment in your current project:\n\n.. code-block:: shell\n\n mkdir project-name && cd project-name\n python3 -m venv .venv\n source .env/bin/activate\n pip3 install adafruit-circuitpython-dang\n\nInstalling to a Connected CircuitPython Device with Circup\n==========================================================\n\nMake sure that you have ``circup`` installed in your Python environment.\nInstall it with the following command if necessary:\n\n.. code-block:: shell\n\n pip3 install circup\n\nWith ``circup`` installed and your CircuitPython device connected use the\nfollowing command to install:\n\n.. code-block:: shell\n\n circup install adafruit_dang\n\nOr the following command to update an existing version:\n\n.. code-block:: shell\n\n circup update\n\nUsage Example\n=============\n\n.. code-block:: python\n\n import time\n\n import supervisor\n import terminalio\n from displayio import Group, Palette, TileGrid\n from terminalio import Terminal\n\n import adafruit_dang as curses\n\n\n class Window:\n def __init__(self, n_rows, n_cols, row=0, col=0):\n self.n_rows = n_rows\n self.n_cols = n_cols\n self.row = row\n self.col = col\n\n @property\n def bottom(self):\n return self.row + self.n_rows - 1\n\n def up(self, cursor): # pylint: disable=invalid-name\n if cursor.row == self.row - 1 and self.row > 0:\n self.row -= 1\n\n def down(self, buffer, cursor):\n if cursor.row == self.bottom + 1 and self.bottom < len(buffer) - 1:\n self.row += 1\n\n def horizontal_scroll(self, cursor, left_margin=5, right_margin=2):\n n_pages = cursor.col // (self.n_cols - right_margin)\n self.col = max(n_pages * self.n_cols - right_margin - left_margin, 0)\n\n def translate(self, cursor):\n return cursor.row - self.row, cursor.col - self.col\n\n\n def helloworld_main(stdscr, terminal_tilegrid):\n window = Window(terminal_tilegrid.height, terminal_tilegrid.width)\n stdscr.erase()\n img = [None] * window.n_rows\n\n user_input = \"\"\n user_entered_message = \"\"\n last_key_press = \"\"\n\n def setline(row, line):\n if img[row] == line:\n return\n img[row] = line\n line += \" \" * (window.n_cols - len(line) - 1)\n stdscr.addstr(row, 0, line)\n\n while True:\n header = \"Hello World Adafruit Dang\"\n margin = (window.n_cols - 1 - len(header)) // 2\n setline(1, f\"{' ' * margin}{header}\")\n\n key_press_message = f\"Last key pressed: {last_key_press}\"\n margin = (window.n_cols - 1 - len(key_press_message)) // 2\n setline(4, f\"{' ' * margin}{key_press_message}\")\n\n last_entered = f\"Entered Message: {user_entered_message}\"\n margin = (window.n_cols - 1 - len(last_entered)) // 2\n setline(6, f\"{' ' * margin}{last_entered}\")\n\n user_input_row = window.n_rows - 2\n if user_input:\n setline(user_input_row, user_input)\n else:\n setline(user_input_row, \" \" * (window.n_cols - 1))\n\n status_message_row = terminal_tilegrid.height - 1\n status_message = f\" Adafruit Dang | Demo | Fruit Jam | {int(time.monotonic())}\"\n status_message += \" \" * (window.n_cols - len(status_message) - 1)\n line = f\"{status_message}\"\n setline(status_message_row, line)\n\n k = stdscr.getkey()\n if k is not None:\n if len(k) == 1 and \" \" <= k <= \"~\":\n user_input += k\n last_key_press = k\n elif k == \"\\n\":\n user_entered_message = user_input\n user_input = \"\"\n elif k in {\"KEY_BACKSPACE\", \"\\x7f\", \"\\x08\"}:\n user_input = user_input[:-1]\n\n\n def run_helloworld_main(terminal, terminal_tilegrid):\n return curses.custom_terminal_wrapper(terminal, helloworld_main, terminal_tilegrid)\n\n\n main_group = Group()\n display = supervisor.runtime.display\n font = terminalio.FONT\n char_size = font.get_bounding_box()\n print(f\"char_size: {char_size}\")\n screen_size = (display.width // char_size[0], display.height // char_size[1])\n\n terminal_palette = Palette(2)\n terminal_palette[0] = 0x000000\n terminal_palette[1] = 0xFFFFFF\n\n terminal_area = TileGrid(\n bitmap=font.bitmap,\n width=screen_size[0],\n height=screen_size[1],\n tile_width=char_size[0],\n tile_height=char_size[1],\n pixel_shader=terminal_palette,\n )\n\n main_group.append(terminal_area)\n terminal = Terminal(terminal_area, font)\n\n display.root_group = main_group\n\n run_helloworld_main(terminal, terminal_area)\n\n\nDocumentation\n=============\nAPI documentation for this library can be found on `Read the Docs <https://docs.circuitpython.org/projects/dang/en/latest/>`_.\n\nFor information on building library documentation, please check out\n`this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.\n\nContributing\n============\n\nContributions are welcome! Please read our `Code of Conduct\n<https://github.com/adafruit/Adafruit_CircuitPython_Dang/blob/HEAD/CODE_OF_CONDUCT.md>`_\nbefore contributing to help this project stay welcoming.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A subset of the curses framework. Used for making terminal based applications.",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/adafruit/Adafruit_CircuitPython_Dang"
},
"split_keywords": [
"adafruit",
" blinka",
" circuitpython",
" micropython",
" dang",
" curses",
" terminal",
" ascii",
" ansi",
" tui"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "5ffc9257f58ff494e3656eb80508ebd224f1ef2d8e20670f5ec33e87efa60722",
"md5": "8c9affb866e532876770164cb4d3dddf",
"sha256": "67e5414159a1751cc72103a5936b5c236565bb78b15441c72c4ae2213d37d9d3"
},
"downloads": -1,
"filename": "adafruit_circuitpython_dang-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8c9affb866e532876770164cb4d3dddf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 6814,
"upload_time": "2025-07-23T20:49:09",
"upload_time_iso_8601": "2025-07-23T20:49:09.111271Z",
"url": "https://files.pythonhosted.org/packages/5f/fc/9257f58ff494e3656eb80508ebd224f1ef2d8e20670f5ec33e87efa60722/adafruit_circuitpython_dang-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "ec269f2041a8abf017fcffa7a12898a4e9e8c9fc96ef2309464305ed48d7c704",
"md5": "4971bdec20e04c6cb753a83997d20fb2",
"sha256": "e78a0d2a92d416a093f1f4ffed55c2cac4c68d9582264dea0a6420c5d03b44de"
},
"downloads": -1,
"filename": "adafruit_circuitpython_dang-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "4971bdec20e04c6cb753a83997d20fb2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 25983,
"upload_time": "2025-07-23T20:49:10",
"upload_time_iso_8601": "2025-07-23T20:49:10.030442Z",
"url": "https://files.pythonhosted.org/packages/ec/26/9f2041a8abf017fcffa7a12898a4e9e8c9fc96ef2309464305ed48d7c704/adafruit_circuitpython_dang-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-23 20:49:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "adafruit",
"github_project": "Adafruit_CircuitPython_Dang",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "Adafruit-Blinka",
"specs": []
}
],
"lcname": "adafruit-circuitpython-dang"
}