Thanks to visit codestin.com
Credit goes to github.com

Skip to content

rd4com/ui-terminal-mojo

Repository files navigation

 ╔✨═🪨🪵═🪄🌙═🔮🌟  
 ║ UiTerminalMojo ║  
 ╰══════┼═════─═══╝  

🟢 Upgraded for 25.5.0.dev2025070207
🆕 Checkout this more advanced example: File explorer

Expect changes: Learning by building!

+-60FPS: Don't do I/O in the loop!

(Please read the framework part of the README.MD)

 

🌌 But feel free to clone, experiment.
Feel free to bootstrap a new framework.
🐿️ Grab what you need and enjoy 💝
Expect bugs 🤷 and bugfixes too!
Don't use this 🚧work in progress in production (or for serious things)
It is early here for the enthusiastic community of builders

 

Dependencies
└ No need to install anything extra, just 🔥mojo and 🪄pixi, uv, pip,...

CPU need 🔢SIMD vectors of at least 16 elements (UInt8)
(For events)

Printing some colors and getting a key press is very difficult (complexity).
It would be nice to have this task well done by an external module.

Future plans:
├ Integrate TermBox2 (>=v2.5.0)
│ 🫂Thanks to the person who created it and all the contributors.
└ Integrate Mog and Banjo (Thanks to toasty 👍)

 

Mojo🔥:

💗 Thanks to modular team and all the contributors.
I could not program lower level before mojo existed, now it is fun and learning is easy.

🌟 Thanks to @owenhilyard for feedbacks and encouragements ! Great job to the Pixi team, it work great.

 


 

┼──────────────╮  ️  
│The framework ├─═   
╰──────────────╯     

It is a terminal user interface framework,
where everything scales relatively🪗!

We work inside a user defined while loop,
logic and render on the fly. (+-60FPS)
(no callbacks needed for events)

This "♾️loop" approach is "immediate mode", here is a basic yet important guide:

  1. Please don't do File I/O on each frame
  2. Please don't do HTTP requests on each frame
  3. Don't forget that it is a just an loop
  4. Don't do anything that should not be done many times per second.
    (__copyinit__, ..)

The screen have "infinite scroll" so far,
user can move the 🮰cursor with ⬅️⬆️➡️⬇️.
Pressing shift at the same time,
and the cursor move faster (by 4)

By pressing Enter,
it is possible to click and interact.
Pressing Esc re-center the screen (0,0),
and pressing again exit the app.

The Tab key open/close the left TabMenu,
it is another space for buttons and widgets.
It emerges from the left-side of the screen,
and when "tabbed out", the cursor moves back.
(back where it was in the ui)

The help overlay is a feature enabled by default,
it's home is at the bottom left of the screen,
This 🌱 teaches all the ui keys quickly to users.
It collapse and expand on cursor hover.

Text("clear") | Bg.yellow | Fg.red in ui
if ui[-1].click():
    todos.clear()

 

 ╔🪨═🪨🪵═🪨🪵═🪨🪵  
 ║ To get started ║  
 ╚════════════════╝  
git clone https://github.com/rd4com/ui-terminal-mojo
cd ui-terminal-mojo
pixi shell
pixi run build_pkg
mojo run -I build examples/example_app.mojo

Stay tuned, this is only the first development phase,
it should become a mojo community package (ecosystem) at time.
(to integrate easily into existing projects with: pixi add)

There is an __init__.mojo,
so that in the meanwhile, in your new projects,
it is possible to git clone this repo and just do:

from `ui-terminal-mojo` import *

Please stay away from submodules,
and wait for the pixi add solution,
because pixi does the compatibility versions checks of dependencies.
(example: adding this to a project that uses an unsupported version mojo)
And so things composes with it.

 

╔══════════╗  
║ Features ║  🧰🔨🔧🪚📐  
╚══════════╝  

mouse hover
mouse click
bg fg color
relative -x (refer to previous items)
immediate ! (all in the loop)
animations
layouts
border

 

╔═════════╗  
║ Widgets ║  🎒  
╚═════════╝  

help user overlay 🤩🔦
selection group
value selector
list paginated
notification (with fade-time) plot/chart (SIMD)
percent bar
tab menu 🔄️
checkbox
dropdown
stepper (progress status, numbered steps)
tooltip
slider
ticker
center
ljust
rjust
blink
shake
input
tag

🎨 Some widgets have an theme parameter (example [theme=Fg.magenta]).

 

╔════════════╗  
║ Animations ║  
╚════════════╝  

spinners
animate_time
animate_emojis
animate_simple_inline

 

╔────────╗  
║ Border ║  
╰════════┘  

StyleBorderSimple
StyleBorderCurved
StyleBorderDouble

And a trait StyledBorder for more (example: ╔──╗)

 

With theses basic building blocks,

it is possible to create a lot fast!

(nested scrollable zones are needed of course)

See widgets implementations,
few methods are actually needed to build things.
(design_api.md one day)

ui.start_measuring()
..do nested things.. some_measurement.peek_dimension()
some_measurement^.stop_measuring()
some_completed_measurement.get_dimension()

ui.move_cursor_after(some_completed_measurement^)
ui.move_cursor_below(some_completed_measurement^)

Text("Hello world") | Fg.green in ui

ui[-2].click()
ui[-1].hover()
ui[-1] |= Bg.magenta

start_border and end_border
(to use with measurement api, as borders are measured too!)

Example: creating widgets

🧭 The plan:

🤷🪄👷 (try meet new ideas by building)

 


 

🤗 Menu dropdown:
🪄 (from scratch)

Text("ShowTodos") | Bg.black | Fg.yellow in ui
if ui[-1].click():
    showtodos  = not showtodos

var idx=0
if showtodos:
    for t in todos:
        Text(String(idx,"   ",t[])) in ui
        if ui[-1].click():
            input_todo = todos.pop(idx)
        if ui[-1].hover():
            ui[-1]|=Bg.magenta
        idx+=1

⌨️ Input:

var value = String("Hello!")
var edited = False
input_buffer["edit:"](
    ui, value, edited
)

Move the 🮰 cursor there and press Enter,
⌨️ type an input,
move the cursor elsewhere and that's it! 🪄

 

Examples

In this folder-directory:
📂 examples
🔥 tags
🔥 input
🔥 table
🔥 slider
🔥 tickers
🔥 stepper
🔥 tabmenu
🔥 spinners
🔥 spinners2
🔥 percent bar
🔥 todo list app
🔥 value selector
🔥 selection group
🔥 notification box
🔥 Collapsible menu
🔥 help user overlay
🔥 list view paginated
🔥 checkbox messagebox

 

Learn step by step

In this folder-directory:
📂 learn
🔥 1. Hello World
🔥 2. Hello Button
🔥 3. Hello Palette
🔥 4. Hello Layout
🔥 5. Hello widgets
🔥 6. Hello composition
🔥 7. Hello Layout 2
🔥 8. Hello customized border
🔥 9. Hello plot/chart

 

📐📏 Layouts:

With few tools,
it is possible to measure and move the cursor.

A measurement (LinearType) is used,
to move the cursor below or after an area.

By nesting measurements,
outer areas relatively scale to nested areas.

                 ┌─┐  ┌─┐
start_measuring─►│A│┌─│D│
                 │B││ │E│
stop_measuring ─►│C││ └─┘
                 └┬┘│
                  └─┘
ui.move_cursor_after(m)

 


 

Note:
The ui automatically append and move the cursor below,
measuring is not needed to vertically append:

"First element" in ui
"Second" in ui

Result is:

First element
Second

Creating layouts can be learned when needed.

 


Why LinearType ?

A started measurement cannot go out of scope,
it can only become a completed measurement.
Which can only by consumed by moving the cursor.
(And all of theses can only be done explicitly)

 

How measurements can scale and compose:
Start measuring (a rectangle)
my_fancy_widget()
Stop measuring

This composes dynamically,
because we let the widget do whatever it needs.
Then just move the cursor below or after it.
And this rectangle is the area that the widget used.
So by moving below or after it, no overlap !

But measurements are to be done in an orderly fashion,
they don't solve all the possible bugs,
removes a lot so far, which is good.

 

So layouts like theses can scale:

While True:
 ↓ Cursor starts here
 ┌─────────────────────────┐┌────┐
 └─────────────────────────┘│    │
 ┌────┐┌───────────────────┐│    │
 │    ││┌───┐   ┌─┐┌─────┐ ││    │
 │    │││   │   │ ││     │ ││    │
 │    ││└───┘   └─┘│     │ ││    │
 │    ││┌──────┐   │     │ ││    │
 │    │││┌─┐┌─┐│   │     │ ││    │
 │    │││└─┘│ ││   └─────┘ │└────┘
 │    │││   └─┘│   ┌─────┐ │┌────┐
 └────┘│└──────┘   └─────┘ ││    │
       └───────────────────┘│    │
       ┌───────────────────┐│    │
       │                   ││    │
       └───────────────────┘└────┘

In this loop, the ui is created dynamically.
If an area grows, the outer one too (relatively).

 


 

MAX and Mojo usage and distribution are licensed under the MAX & Mojo Community License

About

terminal ui mojo programming language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages