Add minimal terminal FFI for raw input mode #274

Closed
opened 2026-01-18 13:19:25 +00:00 by navicore · 3 comments
navicore commented 2026-01-18 13:19:25 +00:00 (Migrated from github.com)

Use Case

Enable vim-style line editing in pure Seq applications (like seq-lisp's REPL) without depending on Rust crates like vim-line.

Currently, Seq exposes readline via libedit FFI, which returns complete lines after Enter is pressed. This makes it impossible to implement character-by-character input handling needed for:

  • Vim modal editing (normal/insert/visual modes)
  • Single-key commands (j, k, dd, x, etc.)
  • Escape key detection for mode switching
  • Real-time cursor movement within input

Requested Primitives

A minimal terminal FFI (~4 functions) would enable implementing vim-line-style editing in pure Seq:

terminal.raw-mode    ( Bool -- )           # Enable/disable raw mode (no line buffering)
terminal.read-char   ( -- Int )            # Read single byte/char (blocking)
terminal.read-char?  ( -- Int Bool )       # Read single byte (non-blocking), returns success flag
terminal.write       ( String -- )         # Write string to terminal (for cursor control)

Optional but useful:

terminal.size        ( -- Int Int )        # Get terminal width height
terminal.flush       ( -- )                # Flush output buffer

Why This Approach

  • Keeps Seq projects pure Seq - no need to pull in Rust crates for line editing
  • Minimal surface area - just expose raw terminal access, implement logic in Seq
  • Reusable - any Seq project could use these primitives (games, TUI apps, etc.)
  • Educational - implementing vim motions in a stack-based language is a fun exercise

Implementation Notes

The underlying implementation would use standard termios (Unix) or similar for raw mode. Libraries like crossterm could be used internally, or direct libc calls.

This would enable seq-lisp to have a vim-style REPL without breaking its "pure Seq" nature. Currently seq-lisp uses libedit's readline which provides emacs-style editing only.

## Use Case Enable vim-style line editing in pure Seq applications (like seq-lisp's REPL) without depending on Rust crates like vim-line. Currently, Seq exposes `readline` via libedit FFI, which returns complete lines after Enter is pressed. This makes it impossible to implement character-by-character input handling needed for: - Vim modal editing (normal/insert/visual modes) - Single-key commands (`j`, `k`, `dd`, `x`, etc.) - Escape key detection for mode switching - Real-time cursor movement within input ## Requested Primitives A minimal terminal FFI (~4 functions) would enable implementing vim-line-style editing in pure Seq: ``` terminal.raw-mode ( Bool -- ) # Enable/disable raw mode (no line buffering) terminal.read-char ( -- Int ) # Read single byte/char (blocking) terminal.read-char? ( -- Int Bool ) # Read single byte (non-blocking), returns success flag terminal.write ( String -- ) # Write string to terminal (for cursor control) ``` Optional but useful: ``` terminal.size ( -- Int Int ) # Get terminal width height terminal.flush ( -- ) # Flush output buffer ``` ## Why This Approach - **Keeps Seq projects pure Seq** - no need to pull in Rust crates for line editing - **Minimal surface area** - just expose raw terminal access, implement logic in Seq - **Reusable** - any Seq project could use these primitives (games, TUI apps, etc.) - **Educational** - implementing vim motions in a stack-based language is a fun exercise ## Implementation Notes The underlying implementation would use standard termios (Unix) or similar for raw mode. Libraries like `crossterm` could be used internally, or direct libc calls. ## Related This would enable seq-lisp to have a vim-style REPL without breaking its "pure Seq" nature. Currently seq-lisp uses libedit's readline which provides emacs-style editing only.
navicore commented 2026-01-18 17:06:18 +00:00 (Migrated from github.com)

Superseded by #276 - implementing as builtins in runtime instead of FFI, which avoids the need for users to build/distribute custom libraries.

Superseded by #276 - implementing as builtins in runtime instead of FFI, which avoids the need for users to build/distribute custom libraries.
navicore commented 2026-01-18 17:16:03 +00:00 (Migrated from github.com)
https://github.com/navicore/patch-seq/issues/276
navicore commented 2026-01-18 18:00:43 +00:00 (Migrated from github.com)
https://github.com/navicore/patch-seq/pull/277
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/patch-seq#274
No description provided.