No description
  • Common Lisp 81.8%
  • TypeScript 16.8%
  • Python 0.6%
  • CSS 0.3%
  • Makefile 0.2%
  • Other 0.2%
Find a file
Hans Hübner 818c7e23d1
Some checks failed
CI / test (push) Has been cancelled
Watch the listener with a deadline instead of waiting in accept
A thread sitting in accept is not woken by another thread closing the socket
under it -- that holds on Linux, where the test suite runs, though not on every
system -- so a listener closed at the end of a test left its thread there for
the life of the process, and the wait for it to end cost five seconds a test.

The wait now has a deadline of its own: a closed listener is noticed within it,
by the wait or by the accept behind it, and the loop ends with the socket.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WKhPX5USQQuBdi6jM5nc7
2026-09-07 06:51:40 +02:00
.github/workflows Fix CI: install s3270 package instead of x3270 2026-03-23 15:15:54 +01:00
CL3270@4073661c74 Update CL3270: negotiation diagnostics go through dbgmsg 2026-08-18 06:34:43 +02:00
editor Fix flaky E2E-SCROLL-FULL-FILE: poll for screen content 2026-04-07 15:02:28 +02:00
examples/guestbook Menu scoping fix, confirmation key-override, test fixtures, dispatch-enter 2026-03-26 14:33:36 +01:00
i18n Prefix framework fields with %, fix list pagination, add i18n page info 2026-03-27 14:30:48 +01:00
screen-editor Add :navigable screen property for command-accessible screens 2026-03-20 23:16:16 +01:00
screens Add PF4 return key, start help at index, fix command field topic navigation 2026-03-24 08:23:17 +01:00
scripts Add test-committed.sh and CI testing guidance 2026-03-24 09:56:48 +01:00
src Watch the listener with a deadline instead of waiting in accept 2026-09-07 06:51:40 +02:00
test Wait for the application thread instead of killing it 2026-09-06 11:03:19 +02:00
.gitignore Initial commit: LISPF application framework 2026-03-19 15:47:26 +01:00
.gitmodules Switch CL3270 submodule URL from SSH to HTTPS 2026-03-23 16:52:03 +01:00
CLAUDE.md Make run-tests require a package argument 2026-03-29 07:06:37 +02:00
lispf.asd Add command registry with define-command macro and show-help-page 2026-03-28 07:34:17 +01:00
load-tests.lisp Move all test files into lispf/tests ASDF system 2026-03-23 15:47:21 +01:00
load.lisp some pushing around on screens + better asdf initialization 2026-03-19 21:47:04 +01:00
README.md Link to example application code from README 2026-03-19 16:13:47 +01:00
run-tests.lisp Move all test files into lispf/tests ASDF system 2026-03-23 15:47:21 +01:00

LISPF — Lisp Interactive Screen Programming Facility

LISPF is an application framework for building interactive IBM 3270 terminal applications in Common Lisp, inspired by IBM's ISPF (Interactive System Productivity Facility). It builds on top of the CL3270 terminal emulation library, which is included as a git submodule.

How it works

Developing a LISPF application follows two steps:

  1. Design screens using the visual screen editor — a web-based WYSIWYG tool that produces .screen files describing field layouts, attributes, colors, and key assignments.

  2. Implement handlers in Lisp — use define-key-handler to respond to PF keys and define-screen-update to populate fields before display. The framework manages screen navigation, session state, field validation, and error display automatically.

Screens are loaded lazily from .screen files at runtime and hot-reloaded when modified on disk, so you can iterate on layouts without restarting the application.

Getting started

Clone the repository with submodules:

git clone --recurse-submodules https://github.com/hanshuebner/lispf

Or, if already cloned:

git submodule update --init

Load the system:

(load "load.lisp")

Example: Guestbook

The included guestbook example (examples/guestbook/) demonstrates a complete multi-screen application with five screens:

  • welcome — ASCII art splash screen, press Enter to continue
  • no-entries — shown when the guestbook is empty, prompts to add the first entry
  • browse — view guestbook entries, PF7/PF8 to page through them
  • new-entry — form with validated name and multi-line message fields
  • bye — session summary showing time spent and entries written

The screens are defined as .screen files in examples/guestbook/screens/. The application logic is roughly 80 lines — session state, key handlers, and a start function:

(asdf:load-system "lispf")
(load (merge-pathnames "examples/guestbook/guestbook.lisp"
                       (asdf:system-source-directory :lispf)))
(lispf-guestbook:start)

Connect with a 3270 terminal emulator (e.g. wx3270) on localhost:3270.

Screen Editor

A web-based WYSIWYG editor for .screen files.

Standalone binary

Build and run:

cd screen-editor && make
./screen-editor --screen-directory examples/guestbook/screens/

This creates a self-contained binary with embedded frontend assets. Open http://localhost:8080 in a browser. Options:

  • --port — HTTP port (default: 8080)
  • --screen-directory — path to .screen files (default: screens/)

Building requires SBCL with Quicklisp, buildapp, and Node.js/npm.

Development mode

Development mode runs the Lisp backend and Vite frontend dev server separately, with hot-reloading on both sides.

Start the Lisp backend:

(load "load.lisp")
(asdf:load-system "lispf-editor")
(screen-editor:start-server "examples/guestbook/screens/" :port 8388)

In a separate terminal, start the Vite dev server:

cd screen-editor/frontend
npm install
npm run dev

Open http://localhost:5173 — the Vite dev server proxies /api requests to the Lisp backend on port 8388.

Prerequisites

  • SBCL with Quicklisp
  • Node.js and npm (for building and developing the screen editor)

License

MIT