Skip to main content

IBM 3270-like terminal UI library for Python

Project description

ux3270

IBM 3270-like terminal UI library for Python.

Documentation | PyPI

Overview

Create terminal applications with an IBM 3270-style interaction model: display a form, let the user fill it in, continue when they submit.

Screenshots

The inventory management demo app showcases the library's capabilities:

Main Menu Inventory List Data Entry Form
Main Menu Inventory List Form
Menu with single-key selection Work-with list with action codes Form with field validation

Installation

pip install ux3270

Or with uv:

uv add ux3270

For development of ux3270 itself:

git clone https://github.com/ljosa/ux3270.git
cd ux3270
uv venv && uv pip install -e .

Quick Start

from ux3270.dialog import Menu, Form, Table, TabularEntry, WorkWithList, SelectionList, show_message

# Create a form with help text
form = Form("DATA ENTRY", help_text="Enter your information")
form.add_field("Name", length=30, required=True,
               help_text="Your full name")
form.add_field("Email", length=40)
result = form.show()  # F1 for help, F3 to cancel
if result:
    print(f"Hello, {result['Name']}!")

# Form with F4=Prompt lookup
def select_dept():
    sel = SelectionList("SELECT DEPARTMENT", ["Code", "Name"])
    sel.add_row(Code="ENG", Name="Engineering")
    sel.add_row(Code="SAL", Name="Sales")
    selected = sel.show()
    return selected["Code"] if selected else None

form = Form("ASSIGNMENT")
form.add_field("Department", prompt=select_dept)  # F4 shows list
result = form.show()

# Work-with list (action codes per row)
wwl = WorkWithList("WORK WITH ITEMS", ["ID", "Name", "Status"])
wwl.add_action("2", "Change")
wwl.add_action("4", "Delete")
wwl.add_action("5", "Display")
wwl.set_add_callback(add_new_item)  # F6=Add
wwl.add_row(ID="001", Name="Item 1", Status="Active")
wwl.add_row(ID="002", Name="Item 2", Status="Inactive")
result = wwl.show()  # Returns [{"action": "2", "row": {...}}, ...]
for item in result or []:
    if item["action"] == "2":
        edit_item(item["row"]["ID"])

# Create a menu
menu = Menu("MAIN MENU")
menu.add_item("1", "Option 1", lambda: print("Selected 1"))
menu.add_item("2", "Option 2", lambda: print("Selected 2"))
menu.run()  # Runs until user exits with F3 or X

# Display a table (with pagination)
table = Table("RESULTS", ["ID", "Name", "Status"])
table.add_row("001", "Item 1", "Active")
table.add_row("002", "Item 2", "Inactive")
table.show()  # F7/F8 to page up/down

# Tabular entry (table with editable columns)
te = TabularEntry("PORTFOLIO UPDATE", panel_id="PORT01")
te.add_column("Ticker", width=8)
te.add_column("Name", width=20)
te.add_column("New Amount", width=12, editable=True, required=True)
te.add_column("Previous", width=12)
te.add_row(Ticker="AAPL", Name="Apple Inc", Previous="1,234.56")
te.add_row(Ticker="GOOGL", Name="Alphabet", Previous="5,678.90")
result = te.show()  # Tab between cells, Enter to submit

# Show a message
show_message("Operation completed", msg_type="success")

Demo App

The inventory management system demonstrates the library:

# Load sample data and run
inventory-app --demo

# Or just run (empty database)
inventory-app

# Other options
inventory-app --help

Keyboard Controls

Context Key Action
All F1 Help
All F3 Cancel/Exit
Forms Tab Next field
Forms Shift+Tab Previous field
Forms Enter Submit
Forms F4 Prompt (show selection list)
Fields Left/Right Move cursor
Fields Home/End Start/end of field
Fields Delete Delete at cursor
Fields Backspace Delete before cursor
Fields Insert Toggle insert/overwrite mode
Fields Ctrl+E Erase to end of field
Menus 1-9, A-Z Select item
Tables/Lists F7 Page backward
Tables/Lists F8 Page forward
Tables Enter Return
Selection Lists S Select item
Work-with Lists 1-9, A-Z Enter action code
Work-with Lists Enter Process actions
Work-with Lists F6 Add new record
Tabular Entry Tab Next editable cell
Tabular Entry Shift+Tab Previous editable cell
Tabular Entry Enter Submit all values

Terminal Width

Tables and lists automatically adapt to terminal width:

  • Uses actual terminal width (not hardcoded 80 columns)
  • Short columns are preserved at natural width
  • Long columns are truncated to fit available space
  • Truncated content shows > indicator (e.g., "Very long tex>")

IBM 3270 Colors

The library uses IBM 3270 color conventions:

  • Green: Input fields
  • Turquoise: Labels (protected fields)
  • White: Titles, headers (intensified)
  • Red: Error messages
  • Yellow: Warnings

Requirements

  • Python 3.10+
  • Unix-like system (Linux, macOS)
  • Terminal with ANSI support

Development

Building and Viewing Documentation Locally

uv run mkdocs serve

Then open http://127.0.0.1:8000 in your browser. The site auto-reloads on changes.

Regenerating Screenshots

Screenshots require Docker with VHS:

./screenshots/generate.sh

Cutting a Release

The version number must be updated in two places that must match:

  1. pyproject.toml: The version field (e.g., version = "0.2.0")
  2. Git tag: Must be v + version (e.g., v0.2.0)

Release process:

# 1. Update version in pyproject.toml
#    Edit: version = "0.2.0"

# 2. Commit the version bump
git add pyproject.toml
git commit -m "Bump version to 0.2.0"

# 3. Create and push tag (triggers release workflow)
git tag v0.2.0
git push origin main --tags

The GitHub Actions workflow will automatically:

  • Build and publish the package to PyPI
  • Deploy versioned documentation to GitHub Pages

Documentation Versions

Documentation is versioned using mike. Each release gets its own version, with latest always pointing to the most recent release. Users can switch versions using the dropdown in the docs.

License

MIT

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

ux3270-1.1.0.tar.gz (884.0 kB view details)

Uploaded Source

Built Distribution

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

ux3270-1.1.0-py3-none-any.whl (43.8 kB view details)

Uploaded Python 3

File details

Details for the file ux3270-1.1.0.tar.gz.

File metadata

  • Download URL: ux3270-1.1.0.tar.gz
  • Upload date:
  • Size: 884.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ux3270-1.1.0.tar.gz
Algorithm Hash digest
SHA256 0daf7f305975ba2e2d3e4e522f40bebe60fd6ff58a02781cb973567d215a1d06
MD5 5d4aaed5c44ac1ea98c8496a8727f54b
BLAKE2b-256 16fdb0607d41d173378fd2edb1451d020f28d6e0aa3e8f08db5d2160eb232ef7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ux3270-1.1.0.tar.gz:

Publisher: release.yml on ljosa/ux3270

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ux3270-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: ux3270-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 43.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ux3270-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 82ddbfe79d19971ecc6a3245f1d4fe9d24df521c97945e1caf815abf4579ad42
MD5 ffc4cfb9918cfbe7fa071629f24a1a5e
BLAKE2b-256 70bc78d179acb198ad3ea0799aa3819ca2ba3056f2586bfee396cff39012d77a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ux3270-1.1.0-py3-none-any.whl:

Publisher: release.yml on ljosa/ux3270

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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