shade40 / celx

A modern terminal UI framework powered by hypermedia served over HTTP.
MIT License
28 stars 0 forks source link

Screenshots #1

Open stephenlf-ems opened 10 months ago

stephenlf-ems commented 10 months ago

I love this project! Can you add some screenshots so we can see what it looks like? Maybe also a small demo showing how to consume content from the server from the command line?

bczsalba commented 6 months ago

Whew, I completely missed this! I've been on a massive programming hiatus for a while now, but I plan on restarting things in the coming weeks. I'll add some screenshots then :)

What do you mean by consuming content from the server from the command line?

stephenlf-ems commented 6 months ago

I guess I've just never seen Hypermedia to render TUIs. How does that work? Can we see it in action?

bczsalba commented 6 months ago

I like to think of celx more as a browser than just a framework, i.e. Chrome instead of React (and I guess React's place would be taken by Celadon), but one that consumes a special XML schema as opposed to HTML (which in itself is a special XML schema, but that's a conversation for a different day).

Here's a small example. I'm writing it in PHP since it's about the simplest looking router I can think of making, but the beauty of the system is any language with any templating solution should work for the same causes.

Note that <?= $something ?> is a shorthand for <?php echo $something ?>, just in case that bit of PHP syntax is confusing.

<?php
$route = $_SERVER["REQUEST_URI"];
$parts = explode("/", $route);
$page = $parts[1];

// Handle a phony "update-resource" POST call
if ($_SERVER["REQUEST_METHOD"] == "POST" && $page == "update-resource") {
    echo "<text>The time is " . date("h:i:sa") . "</text>";
    return;
}

// A simple component with some repeated styling. You could also put these
// styles into a Yaml file, and select something like `#nav *> link`!
function nav_link(string $text, string $link, bool $current = false) { ?>
    <link to="<?= $link ?>">
        <style>
            /hover:
                content_style: underline

            <?php if ($current): ?>content_style: bold<?php endif; ?>
        </style>
        <?= $text ?>
    </link>
<?php } ?>

<celx version="0">
    <page>
        <tower>
            <style> frame: light </style>
            <row>
                <text>
                    <style> width: null </style>
                    Welcome!
                </text>
                <row>
                    <?= nav_link("Blog", "/blog", $page == "blog") ?>
                    <?= nav_link("History", "/history", $page == "history") ?>
                    <?= nav_link("Dogfood", "/dogfood", $page == "dogfood") ?>
                </row>
            </row>
            <tower>
                <!--
                    Some styling for this tower, and some for any Towers that are direct
                    descendants (`>`) of it.
                -->
                <style>
                    frame: padded
                    alignment: [center, start]

                    \> Tower:
                        alignment: [center, center]
                        gap: 1
                </style>
                <text>This is the "/<?= $page ?>" page. Hello!</text>
                <tower>
                    <!-- A simple increment button, using Lua. -->
                    <button>
                        Count: $count
                        <script>
                        count = 0

                        function on_submit(btn)
                            count = count + 1
                            return true
                        end
                        </script>
                    </button>
                    <!--
                        A server button, using our hypermedia instruction language
                        Chocl. Sends a POST request to /update-resource, and swaps its
                        result in as the content of #output.

                        Equivalent to:
                            hx-post="/update-resource"
                            hx-target="#output"
                            hx-swap="innerHTML" (though this one is default for HTMX)
                    -->
                    <button on-submit="POST /update-resource; swap in #output">
                        Ask and ye shall receive
                    </button>
                </tower>
                <tower eid="output"></tower>
            </tower>
        </tower>
    </page>
</celx>

This creates a (very simple) application that's pretty similar to a basic website. It has some routing using the <link> elements, interactivity both client side (with Lua) and server side (using an HTMX inspired system).

And here is the result:

Screenshot 2024-03-05 at 21 19 55

Ultimately it's my favorite way to write TUIs I've found so far, as it avoids most of the gunk that current solutions have. No one really likes writing curses/ncurses apps, and I've always thought there was about 15 layers too many in the Textual codebase. This is mostly personal opinion, but I've found Hypermedia really does solve these issues quite conveniently.


Some of the layout engine is a bit all over the place, it's one of my primary goals to have fixed before 1.0. I also want celx to be an open standard, so I plan to create a detailed specification of the XML format, markup language, styling & layout systems before going stable.

Thank you for your interest! I've been off from programming for a minute, this is the exact kind of comment I needed to dust off this project. Very excited for the future!

HilkopterBob commented 5 months ago

Hey! That actually sounds pretty cool as a TUI-App Backend! Would you mind creating a minimal working example in python? That is currently the only problem i have found before using this library as backend for an Editor for my Textadventure-Engine!