nandi/jolt-nativepublic Fork 0
0fb017593acce485b16f9756141b599beb49dc76
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Paint the same tree into a terminal, for the machines with no window a7f6202 · on 0fb017593acce485b16f9756141b599beb49dc76 · nandi · 17d ago
showcase.rs · 109 lines · 3.4 KBRust Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
//! Every tag this backend has, driven through the C ABI itself.
//!
//!     cargo run -p jolt-tui --example showcase
//!
//! It calls `tui_*` exactly as jolt does — nodes by handle, props by name,
//! events polled off a queue — so it doubles as a check that the ABI is usable
//! from the outside and not only from the inside.
//!
//! Tab and Shift-Tab move, Enter and Space activate, j/k and the arrows move
//! the list, the wheel scrolls, Ctrl-C or Ctrl-Q quits.

use std::ffi::{CStr, CString};

use jolttui::*;

fn node(tag: &str) -> i32 {
    let tag = CString::new(tag).unwrap();
    unsafe { tui_node_new(tag.as_ptr()) }
}

fn set(id: i32, key: &str, value: &str) {
    let (key, value) = (CString::new(key).unwrap(), CString::new(value).unwrap());
    unsafe { tui_node_set_str(id, key.as_ptr(), value.as_ptr()) }
}

fn set_num(id: i32, key: &str, value: f64) {
    let key = CString::new(key).unwrap();
    unsafe { tui_node_set_num(id, key.as_ptr(), value) }
}

fn get(id: i32, key: &str) -> String {
    let key = CString::new(key).unwrap();
    unsafe { CStr::from_ptr(tui_node_get_str(id, key.as_ptr())) }
        .to_string_lossy()
        .into_owned()
}

fn child(parent: i32, tag: &str, props: &[(&str, &str)]) -> i32 {
    let id = node(tag);
    for (key, value) in props {
        set(id, key, value);
    }
    tui_node_append(parent, id);
    id
}

fn main() {
    if tui_open(1) == 0 {
        eprintln!("showcase: this example needs a terminal");
        return;
    }
    let root = tui_tree_root();
    let page = child(root, "vbox", &[]);
    set_num(page, "margin", 1.0);
    set_num(page, "spacing", 1.0);

    child(page, "title", &[("label", "jolt-tui")]);
    let status = child(
        page,
        "dim-label",
        &[("label", "tab moves · enter activates · ctrl-c quits")],
    );

    let row = child(page, "hbox", &[("orientation", "horizontal")]);
    set_num(row, "spacing", 2.0);
    child(row, "button", &[("label", "count")]);
    child(
        row,
        "button",
        &[("label", "reset"), ("kind", "destructive")],
    );
    child(row, "checkbutton", &[("label", "live")]);

    child(page, "entry", &[("placeholder", "type something")]);
    let bar = child(page, "progress", &[("label", "")]);
    let frame = child(page, "frame", &[("label", "Rows")]);
    let list = child(frame, "listbox", &[]);
    for name in ["alpha", "beta", "gamma", "delta"] {
        child(list, "label", &[("label", name)]);
    }

    let mut count = 0.0f64;
    while tui_should_close() == 0 {
        tui_tick(50);
        while tui_tree_poll_event() == 1 {
            let node = tui_tree_event_node();
            let name = unsafe { CStr::from_ptr(tui_tree_event_name()) }
                .to_string_lossy()
                .into_owned();
            let text = unsafe { CStr::from_ptr(tui_tree_event_text()) }
                .to_string_lossy()
                .into_owned();
            match name.as_str() {
                "click" => {
                    let label = get(node, "label");
                    count = if label == "reset" { 0.0 } else { count + 1.0 };
                    set_num(bar, "value", (count / 10.0).min(1.0));
                    set(status, "label", &format!("{label}: {count}"));
                }
                "select" | "activate" | "toggled" | "change" => {
                    set(status, "label", &format!("{name} {text}"));
                }
                _ => {}
            }
        }
        tui_frame();
    }
    tui_close();
}