Skip to content

v0.8.0 — the missing basics

Choose a tag to compare

@thatsme thatsme released this 15 Sep 07:13
· 14 commits to main since this release

What a terminal UI library has to provide because an application cannot: a
terminal that reflows when resized, text with more than one style, handing the
terminal to another program and back, job control, and the mouse. Two of those
were not features but defects found on the way — resize had never worked
outside tests, and a crash in update/2 left the terminal broken.

Fixed:

  • Resizing the terminal reflows the app. It never did outside tests: Keeper
    waited for a message OTP never sends, because handled signals go to the
    erl_signal_server event manager, not the caller. A redraw after a resize now
    also clears the screen instead of leaving the old frame's borders behind.
  • A crash in update/2 restores the terminal. The runtime was a :temporary
    child, whose crash shuts nothing down; the terminal stayed raw on the
    alternate screen with Harlock.run waiting forever.
  • Harlock.run/3 returns {:error, reason} when the app goes down, as documented,
    instead of the caller being killed by its link to the supervisor.
  • Ctrl-Y yanks in routed text_input and textarea; routing had passed an empty
    kill ring. The runtime now holds one ring for the app.
  • examples/contacts.exs accepts typing again: it matched raw keys that routing
    has delivered as {:harlock_edit, ...} since v0.4.
  • Documentation brought up to date with the code throughout — README, module
    docs, examples, the native-code guide and the roadmap — including element
    docs that still told apps to call apply_key themselves, and a docs sidebar
    that now groups every public module.

Added:

  • Styled, multi-line and wrapped text: text/2 accepts runs such as
    ["CPU ", {"92%", fg: :red}], with wrap: and align:, and Harlock.Text.height/2
    for sizing a viewport around wrapped text.
  • button/2 and checkbox/2, routed like the other widgets.
  • Cmd.exec/3 runs a program — an editor, a pager, git commit — with the
    terminal and resumes the app when it exits. The program is started from the
    termios NIF as the terminal's foreground process group, because anything the
    BEAM starts through a port has no controlling terminal. Builds a second
    binary, priv/harlock_exec, at install.
  • Cmd.suspend/0: Ctrl-Z to the shell, fg to come back, for apps that bind it.
  • Mouse support with Harlock.run(app, arg, mouse: true): clicks focus elements
    and act on buttons, checkboxes, table rows, menu items, tree nodes and
    markers, tabs, select choices and text input positions; the wheel scrolls.
    Reporting is turned off on every way out.
  • examples/nodes.exs, a BEAM node explorer, and keyboard routing for table.

Changed:

  • A focusable table consumes navigation keys that previously reached update/2
    (opt out with handle_keys: false). "\n" in a text binary starts a new line.

Apps must be run with mix run, not from an IEx prompt, whose terminal driver
competes for the same tty.

Every terminal behaviour here is checked in a real pty on macOS and Linux by
the smoke tests in priv/, which run in CI. Upgrade notes and the full list are
in CHANGELOG.md.