Sign in

    LunarEvent

    MoonBit terminal event API backed by TerminalEvent C FFI

    terminal
    event
    tui
    Download zip
    Version
    0.1.1
    License
    Apache-2.0
    Last updated
    4 months ago
    Downloads
    121

    #LunarEvent

    LunarEvent is a MoonBit-friendly terminal event layer backed by the stable C FFI surface published by TerminalEvent.

    It keeps the C and C++ implementation boundary outside downstream MoonBit projects. Applications import MoonBit packages only; they do not include or reference TerminalEvent's C++ headers or source files.

    #Package Boundary

    • FrozenLemonTee/TerminalEvent/moonbit/lte_native owns the raw lte_* C ABI binding.
    • FrozenLemonTee/LunarEvent maps the raw ABI into MoonBit Event and EventBackend types.
    • FrozenLemonTee/LunarEvent/lunartui adapts LunarEvent events into LunarTUI @base.Event values.
    • FrozenLemonTee/LunarTUI remains independent from LunarEvent and TerminalEvent.

    The dependency direction is intentionally one-way at each layer:

    TerminalEvent C++ core -> TerminalEvent C ABI -> TerminalEvent MoonBit FFI -> LunarEvent -> LunarTUI adapter -> application

    #Installation

    moon add FrozenLemonTee/LunarEvent

    Or add it manually to moon.mod:

    import {
    "FrozenLemonTee/LunarEvent@0.1.0",
    }

    LunarEvent currently targets MoonBit native builds.

    #Core Event API

    The root package exposes a terminal event model that is independent from LunarTUI widgets:

    • Event::Key(KeyEvent) for keyboard input.
    • Event::Resize(ResizeEvent) for terminal size changes.
    • Event::Paste(String) for pasted text.
    • Event::Mouse(MouseEvent) for mouse activity.
    • Event::Focus(FocusEvent) for focus gained/lost notifications.
    • Event::Unknown(String) for raw input that the backend could not classify.

    EventBackend owns the runtime bridge to TerminalEvent's C FFI:

    let backend = @LunarEvent.EventBackend::new()
    match backend.enter_raw_mode() {
    Ok(_) => {
    match backend.poll_event(32) {
    Some(event) => {
    // Route the event into your application.
    ignore(event)
    }
    None => ()
    }
    backend.restore_terminal()
    }
    Err(_) => ()
    }
    backend.shutdown()

    The timeout passed to poll_event is in milliseconds. None means no event was available or the backend reported no event.

    #LunarTUI Adapter

    The lunartui subpackage is the default bridge for LunarTUI applications:

    let source = @lunartui.EventSource::new()
    match source.enter_raw_mode() {
    Ok(_) => {
    match source.poll_event(32) {
    Some(event) => {
    // event is a LunarTUI @base.Event
    ignore(event)
    }
    None => ()
    }
    source.restore_terminal()
    }
    Err(_) => ()
    }
    source.shutdown()

    The adapter maps LunarEvent values into LunarTUI's terminal-agnostic event protocol:

    LunarEventLunarTUI
    Event::Key@base.Event::key
    Event::Resize@base.Event::resize
    Event::Paste@base.Event::text_input
    Event::Mouse@base.Event::mouse
    Event::Focus@base.Event::focus
    Event::Unknowndropped by the adapter

    #Backend Notes

    The current TerminalEvent backend is POSIX-oriented. On Windows, raw mode may report unavailable unless the program is executed in a compatible POSIX terminal environment.

    • TerminalEvent: C++ terminal event backend and C ABI.
    • LunarTUI: MoonBit TUI widgets, layouts, rendering, and event protocol.
    • TextEditor: interactive demo using TerminalEvent, LunarEvent, and LunarTUI together.

    Event

    pub(all) enum Event {
    Key(KeyEvent)
    Resize(ResizeEvent)
    Paste(String)
    Mouse(MouseEvent)
    Focus(FocusEvent)
    Unknown(String)
    } derive(Eq)

    EventBackend

    pub struct EventBackend {
    }

    EventBackend::enter_raw_mode

    fn EventBackend::enter_raw_mode(self : EventBackend) -> Result[Unit, TerminalError]

    EventBackend::new

    EventBackend::poll_event

    fn EventBackend::poll_event(self : EventBackend, timeout_ms : Int) -> Event?

    EventBackend::restore_terminal

    fn EventBackend::restore_terminal(self : EventBackend) -> Unit

    EventBackend::shutdown

    fn EventBackend::shutdown(self : EventBackend) -> Unit

    EventBackend::terminal_size

    fn EventBackend::terminal_size(self : EventBackend) -> Result[Size, TerminalError]

    EventStream

    pub struct EventStream {
    buf : Array[Event]
    }

    impl Add for EventStream

    EventStream::add

    fn EventStream::add(self : EventStream, event : Event) -> EventStream

    EventStream::add_all

    fn EventStream::add_all(self : EventStream, stream : Array[Event]) -> EventStream

    EventStream::new

    fn EventStream::new(stream : Array[Event]) -> EventStream

    FocusEvent

    pub(all) struct FocusEvent {
    state : FocusState
    } derive(Eq)

    FocusState

    pub(all) enum FocusState {
    Gained
    Lost
    } derive(Eq)

    KeyCode

    pub(all) enum KeyCode {
    Character
    Enter
    Escape
    Backspace
    Tab
    Left
    Right
    Up
    Down
    Home
    End
    PageUp
    PageDown
    Insert
    Delete
    Function(Int)
    Unknown
    } derive(Eq)

    KeyEvent

    pub(all) struct KeyEvent {
    code : KeyCode
    text : String?
    modifiers : Modifiers
    } derive(Eq)

    Modifiers

    pub(all) struct Modifiers {
    shift : Bool
    ctrl : Bool
    alt : Bool
    meta : Bool
    } derive(Eq)

    Modifiers::new

    fn Modifiers::new(shift? : Bool, ctrl? : Bool, alt? : Bool, meta? : Bool) -> Modifiers

    MouseAction

    pub(all) enum MouseAction {
    Move
    Down
    Up
    Drag
    Scroll
    Unknown
    } derive(Eq)

    MouseButton

    pub(all) enum MouseButton {
    Left
    Right
    Middle
    Back
    Forward
    Unknown
    } derive(Eq)

    MouseEvent

    pub(all) struct MouseEvent {
    button : MouseButton
    action : MouseAction
    x : Int
    y : Int
    modifiers : Modifiers
    } derive(Eq)

    ResizeEvent

    pub(all) struct ResizeEvent {
    width : Int
    height : Int
    } derive(Eq)

    Size

    pub(all) struct Size {
    width : Int
    height : Int
    } derive(Eq)

    TerminalError

    pub(all) enum TerminalError {
    NativeError(Int)
    } derive(Eq)

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io