Skip to content

Latest commit

 

History

History
134 lines (95 loc) · 4.7 KB

File metadata and controls

134 lines (95 loc) · 4.7 KB

Pages

  1. Getting started
  2. Layouts
  3. Styling
  4. Components
  5. Writing component

Getting started

Hello world!

image

Above is result of hello_world.sh in examples folder

Here its code

source ../src/lib.sh

init_screen

layout.create_from_screen Layout

rect.new rect1
rect.get_layout rect1 layout_inside_rect
label.new label1 "Hello world!"
label.set_text_align label1 center center

rect.draw rect1 Layout
label.draw label1 layout_inside_rect
buffer.flush
sleep 10
exit_screen

Lets break it down

source ../src/lib.sh - First, we import library, you should source a single entry file, located at src - lib.sh

then when you are ready to enter into rendering mode, you call init_screen which set up screen alternative mode, buffer properties, subscribes to terminal events, for example reszie or exit event when you press ctrl+c. Also the last line - exit_screens clears all changes that were made during init_screen

To render component, you need to know where you want to render it. For that purpose layout is created, which will be described in later pages, but for now you need to create a layout, that will take full width and height of terminal.

layout.create_from_screen Layout, where Layout is name of layout, you can have many layouts with different names.

rect.new rect1 - creates new rectangle component, with name of rect1 rect.get_layout rect1 layout_inside_rect - creates layout, inside rect1 component. This layout will take size of rect, excluding its borders.

    label.new label1 "Hello world!"
    label.set_text_align label1 center center

First line creates a new label component with name of label1 and text "Hello world!".

On second line we say, that label1 component should show its text in horizontal and vertical center. Supported values are start center end.

    rect.draw rect1 Layout
    label.draw label1 layout_inside_rect

Theese two lines renders corresponding components in given layouts. Here, rect1 is rendered in Layout that was created with full screen size, meaning that rect will take full width and height, and label within layout_inside_rect, which size is rect1 layout excluding borders.

Note that if we change render order to

    label.draw label1 layout_inside_rect
    rect.draw rect1 Layout

The label wont be drawn. Why? Because layout layout_inside_rect handled by rect1 and recalculated every draw. That means that this layout size is not computed yet and equals to zeros.

And last line

    buffer.flush

This library works in immediate mode, which means that all components needs to be drawn every frame. After we draw all components, that we wanted to be show in screen, we say to buffer, that it can finally show our bellowed frame and print it to screen.

Now lets say we want to have a variable, increment it every frame, and show its value.

img

We take our script written above and slightly modify it.

Code of hello_world_increment.sh below

source ../src/lib.sh

init_screen

layout.create_from_screen Layout

rect.new rect1
rect.get_layout rect1 layout_inside_rect
label.new label1 "Hello world!"
label.set_text_align label1 center center

i=0
while [ 1 ]; do
    rect.draw rect1 Layout
    i=$((i + 1))
    label.set_text label1 "Hello world!: $i"
    label.draw label1 layout_inside_rect
    buffer.flush
    sleep 1
done
exit_screen

Now we created a rendering loop, in which all components are drawn. After modifying our i variable we need to say label1, that text is changed.

For that we call label.set_text label1 "Hello world!: $i" which replaces text of label1.

Then we flush our frame, and go to beginning of loop.

User input

Lets say you want to process user input events. You can use built-in bash function read, but default command blocks the loop and waits until enter is pressed. Also, because frame isn't redrawn, resize events also won't be processed, which can lead to unwanted behaviour.

Instead you can use read with args, so it reads a single key and waits for a short period of time

while true; do
    if read -rsn1 -t 0.005 key; then
        # Handle key button
    fi
    # Render frame
done

Note that you need to filter(or process) its output. If, for example, you blindly bind key to label and user presses right arrow, key will be equal to [0m[c, which breaks ui if rendered as single character

Example of unfiltered input in examples/preview.sh