⚙️ ❮ ⬢ ZUI For Zsh Hackers❯
Tags: zsh, tooling, programming, shell
Published: 2022-02-08 15:26:21

![ZUI - Tool of Command Ninja](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckfwat3406ssgqqbv3f2.png)

- ❮ [Zi](https://wiki.zshell.dev/) ❯ **is a fast and feature-rich plugin manager for [Zsh](https://zsh.sourceforge.io/) [Unix]
(https://en.wikipedia.org/wiki/Unix_shell) shell.** 

- ⬢ [ZUI](https://github.com/z-shell/zui/) is **CGI+DHTML-like** User Interface Library for **Zsh / ZCurses** When both setup, I would say - quite a strong combo. 

---

> Note: Got macOS? WTF is Zsh? At this point you should stop reading, and head over - https://z-shell.pages.dev/

However, ❮ [Zi](https://wiki.zshell.dev/) ❯ accompanied with almost [100 repositories](https://github.com/orgs/z-shell/repositories) and some might get ready by China Dev's: [gitee.com/z-shell](https://gitee.com/z-shell/).

Is this not impressive? Well, then include almost all from here: [awesome-zsh-plugins](https://github.com/unixorn/awesome-zsh-plugins) as most are compatible, made by community and actually is awesome :)

-  | [Join the team](https://github.com/z-shell/community/issues/new?assignees=&labels=%F0%9F%91%A5+member&template=membership.yml&title=team%3A+)

- Issue report: [ZUI](https://github.com/z-shell/zui/issue) 

- Wiki + Open-Search: https://wiki.zshell.dev/search/

![ZI open search wiki](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xsa26k4ggw90kvrug95c.png)

---

This is a RAD (Rapid Application Development) textual user interface library for Zsh. It in many aspects resembles a typical CGI+(D)HTML setup. There are:

- Generators ran on the "server" side (basic Zshell-code that is just generating text!),

- Event loop that turns the generated text into a document with active elements (buttons, anchors, toggle buttons, text fields, list boxes),

- Mechanism to regenerate document parts from the original generators.

So, a Zshell code generates text. It is then turned into a document with hyperlinks.
DHTML-like calls are possible that will regenerate document parts on the fly.
Page can be also reloaded with input data, just like an HTML page. A voiced video available on [google drive](https://drive.google.com/file/d/1mg6OPScurIT_AIJPotEzpw1TrnU0OeUZ/view?usp=sharing), that shows how to create an application – **Nmap network scanner frontend**

## Screenshots

[![hello world](https://z.digitalclouds.dev/assets/ideal-img/hello-world-fs8.6811b86.903.png)](https://z.digitalclouds.dev/assets/ideal-img/hello-world-fs8.6811b86.903.png)

**Text-fields demo, showing what color "default" can do:**

[![text fields](https://z.digitalclouds.dev/assets/ideal-img/zui-text-fields-fs8.9b6ac89.905.png)](https://z.digitalclouds.dev/assets/ideal-img/zui-text-fields-fs8.9b6ac89.905.png)

**List-boxes demo:**

[![list boxes](https://z.digitalclouds.dev/assets/ideal-img/zui-list-boxes-fs8.a3bc270.903.png)](https://z.digitalclouds.dev/assets/ideal-img/zui-list-boxes-fs8.a3bc270.903.png)

**History demo – fully functional history tool with the incremental search:**

[![history demo](https://z.digitalclouds.dev/assets/ideal-img/zui-history-fs8.2162405.902.png)](https://z.digitalclouds.dev/assets/ideal-img/zui-history-fs8.2162405.902.png)

**Text Editor demo, written in 30 minutes:**

[![text editor](https://z.digitalclouds.dev/assets/ideal-img/zui-edit-fs8.e4d0000.904.png)](https://z.digitalclouds.dev/assets/ideal-img/zui-edit-fs8.e4d0000.904.png)

## Asciinema

Videos on the service `Asciinema`, where you can resize the video like a normal web page, and select/copy text.

**List boxes, text fields:**

[![asciicast](https://asciinema.org/a/107691.png)](https://asciinema.org/a/107691)

**Text editor written in 30 minutes:**

[![asciicast](https://asciinema.org/a/107800.png)](https://asciinema.org/a/107800)

**Configure/Make wrapper:**

[![asciicast](https://asciinema.org/a/107688.png)](https://asciinema.org/a/107688)


### Learning Zsh

ZUI will allow you to learn Zsh at an advanced level. The library uses Zshell as e.g. Ruby. To write a functional program in Ruby, you need to know the language. To write a command or alias in Zsh, you can spend years not learning anything new. With ZUI you will learn how to use `coproc`, patterns with `(#b)` flag, Zstyles, arrays, hashes, and various substitutions. That said, examples are there to make the process easy, and problems have an easy and advanced way of solving.

### API

The API consists of [Standard Library](#standard-library), [Utilities Library](#utilities-library) and [Callbacks](#callbacks). You normally want a few calls from Standard Library – to create buttons and regenerate document parts, and one or two callbacks. The fastest way to learn ZUI is to look at [Hello World example](https://github.com/z-shell/zui/blob/main/demos/zui-demo-hello-world) and other [example codes](https://github.com/z-shell/zui/tree/main/demos) like the [timeout example](https://github.com/z-shell/zui/blob/main/demos/zui-demo-timeout).

## Standard Library

Standard Library contains functions to:

- initialize and cleanup an application,
- load and set application's configuration,
- create hyperlinks (buttons, anchors, text fields, list boxes),
- handle hyperlinks (e.g. check if the given text is a hyperlink),
- control document regeneration on-the-fly (the DHTML-like way),
- handle modules (e.g. read module's position in the document),

### Calls of Standard Library

Below are descriptions of Standard Library functions. Arguments in triangular brackets are mandatory, in square brackets – optional.

---

#### -zui_std_init

```zsh
-zui_std_init [app:"application ID"] [app_name:"Application name"]
```

Initializes application. To be called **before emulating**. Optional argument `app:...` will set `ZUI[app]` – hash field needed by any application. Argument `app_name:` does the same for `ZUI[app_name]` (it is a human-readable application name, displayed in header).

---

#### -zui_std_init2

```zsh
-zui_std_init2
```

Initialization to be called **after emulating**. `emulate` is the command that makes a function an independent program and each ZUI application should use it.

---

#### -zui_std_stalog

```zsh
-zui_std_stalog <Text 1> [Text 2] ...
```

Appends a message to the status window logs. Each text argument has a color assigned – see the `log_colors` [Zstyle](#Zstyles), it controls the colors.

---

#### -zui_std_special_text

```zsh
-zui_std_special_text <text> [output array]
reply+=( "{output string}" )
```

Quote special characters in the text. This allows to use of strings like `That's` in the document – special character `'` will not disturb content. The default output array is `reply`.

---

#### -zui_std_button_ext

```zsh
-zui_std_button_ext <ID> <data1> <data2> <data3> <data4> <button text> [handler] [output array]
```

Creates string with the button. Every button has an ID assigned – it is the first argument. Then go four user-data arguments – if the handler will be invoked, the user-data will be passed to it along with the ID. `<button text>` is the label of the button. `[handler]` is the function name or inline code to be called at the press of the button. `[output array]` name can be provided to have the result appended to that array (the default array is `reply`). If a handler has a substring "internal" in it (in function name or inline code), then it will be invoked without list restart. Otherwise, a list restart will be performed (this is like invoking JavaScript without web page reload, or doing the reload and calling code on the server-side).

---

#### -zui_std_rc_button_ext

```zsh
-zui_std_rc_button_ext <ID> <data1> <data2> <data3> <data4> <button text> [handler] [output array]
```

The function works identically to `-zui_std_button`, but it wraps button text in square brackets – "RC" is for "rectangular". Also, both functions have no-`_ext` versions that do not have `<data1>`...`<data4>` arguments.

---

#### -zui_std_anchor

```zsh
-zui_std_anchor <ID> <index> <data1> <data2> <data3> <button text> [handler] [output array]
```

Creates an anchor – a hyperlink that moves the cursor to the specified line. Appends it to `[output array]` (a parameter specified by name) – `reply` by default. `<index>` is the line number to jump to. It is relative to the current module. It, in general, cannot point to the absolute line number in the document. To point to line outside the module, use `A+B` syntax, e.g. `1-2`, to jump `2` lines before the first line of the module. Instead of the handler, you may use `<data2>` and `<data3>` to pass a module regeneration instruction. For example, pass `",mod2_ice1,"` `"arg"` to regenerate some module numbered 2, instance 1, with passed user-data "arg". This regeneration is with list restart (i.e. it is like web page reload with `arg` passed to script on the server-side). If the handler has a substring "internal" in it (in function name or inline code), then the anchor will be internal – will not cause the document to reload. Anchor of which `<data2>` matches `,*,` is set to be external. Example call:

```zsh
-zui_std_anchor regen1 4 "" ",mod1_ice1," $RANDOM "[${ZUI[MAGENTA]}Regen${ZUI[FMT_END]}]"
```

This instructs to regenerate module `1` instance `1`, with no handler call, with `$RANDOM` as generator's third input - regeneration user-data. `4` is the line number on which the cursor will be placed after the regeneration. Note that any generator call has instance ID (mod and ice) in `$1` and `$2` by the design of restart-regeneration loop.

---

#### -zui_std_text_field

```zsh
-zui_std_text_field <ID> <width param> <index param> <text param> <data1> <data2> <data3> [handler] [output array]
```

Creates text-field. Every text field has width, given indirectly, by supplying **name of variable** holding the width number. In the same way, a start-index is to be provided – it specifies from which character the text should be displayed (so it can e.g. start from the 5th character). `<text param>` is the name of the variable holding the string that the text field contains. The handler will be called on the accept event (i.e. Enter-press; Cancel is ESC-press, it restores previous text-field contents).

---

#### -zui_std_list_box

```zsh
-zui_std_list_box <ID> <width param> <index param> <options param> <data1> <data2> <data3> [handler] [output array]
```

Creates list-box. Every list box has a text width that it will occupy in the document regardless of the option's text length. This width is specified via **name of variable** holding the width number. Current-selected option is `<index param>` – also a variable name. Options are specified by `;`-separated string, put in a variable whose name is passed as the fourth argument (`<options param>`). The handler will be called on the accept event (i.e. Enter-press; Cancel is ESC-press, it restores previous list-box current option).

---

#### -zui_std_get_ganchor

```zsh
-zui_std_get_ganchor <module index> <instance index> <button text>
```

Anchors cannot use global indexes and easily point to other modules. However, there are `top anchors` that point to each module. The top anchors can be hidden. However, they are always accessible by this function. It fetches anchor pointing to module `<module index>`, instance `<instance index>`. The anchor will be having specified `<button text>`. You can use it as any other anchor, with the notable fact that handler cannot be specified, however, a callback will be called on anchor's press: `-zui-standard-global-anchors-callback()`, with anchor's ID in `$1`, line number in `$2`, module index in `$3`, instance index in `$4`.

---

#### -zui_std_decode_hyperlink

```zsh
-zui_std_decode_hyperlink <hyperlink string> [output array]
array=( ID data1 data2 data3 data4 )
```

Decodes given hyperlink (anchor, button, raw link). Its ID and user-data are placed in the array given by name (default is `reply` array). Testable.

---

#### -zui_std_decode_text_field

```zsh
-zui_std_decode_text_field <hyperlink string> [output array]
array=( ID width-param index-param text-param data1 data2 data3 )
```

Decodes given text-field hyperlink. Its ID, names of backend parameters, and user data are placed in the array given by name (default is `reply` array). Testable.

---

#### -zui_std_decode_list_box

```zsh
-zui_std_decode_list_box <hyperlink string> [output array]
array=( ID width-param index-param options-param data1 data2 data3 )
```

Decodes given list-box hyperlink. Its ID, names of backend parameters, and user data are placed in the array given by name (default is `reply` array). Testable.

---

#### -zui_std_decode

```zsh
-zui_std_decode <hyperlink string> [output parameter] [output array]
array=( {data decoded from hyperlink} )
parameter=1|2|3
```

Tries various decoding functions (for regular hyperlinks, text fields, list-boxes). Testable. Returns (in `REPLY` or specified parameter) 1 if recognized regular hyperlink (anchor, button, raw link), 2 if text field, 3 if list-box. Will return 0 for unrecognized string, however, the function is testable so a normal return value test can be performed.

---

#### -zui_std_get_stext

```zsh
-zui_std_get_stext <special-text string> [output parameter]
REPLY={text}
```

Output variable (default: `REPLY`) is set to text contained in the special-text string.

---

#### -zui_std_is_hyperlink

```zsh
-zui_std_is_hyperlink <hyperlink string>
```

Checks if a given string is a regular hyperlink (anchor, button, raw link). Testable (true – the string is a correct hyperlink).

---

#### -zui_std_is_text_field

```zsh
-zui_std_is_text_field <hyperlink string>
```

Checks if a given string is a text field. Testable (true – the string is a correct text field).

---

#### -zui_std_is_list_box

```zsh
-zui_std_is_list_box <hyperlink string>
```

Checks if a given string is a list-box. Testable (true – the string is a correct list-box).

---

#### -zui_std_is_any_hyperlink

```zsh
-zui_std_is_any_hyperlink <hyperlink string> [output parameter]
parameter=1|2|3
```

Checks if a given string is any possible hyperlink, from anchor to list-box. Output parameter (`REPLY` by default) will contain 1 if recognized regular hyperlink, 2 if text-field, 3 if list-box. For unrecognized string it will contain 0, however, the function is testable, so a regular return value check can be performed.

---

#### -zui_std_has_any_hyperlinks

```zsh
-zui_std_has_any_hyperlinks <hyperlink string>
```

Similar to `-zui_std_is_any_hyperlink`, but doesn't return the type of the hyperlink recognized. Testable.

---

#### -zui_std_load_config

```zsh
-zui_std_load_config <variable> <default> <time limit> <output parameter>
```

Loads variable from configuration if it's older than e.g. `2` seconds (the `<time limit>` argument). Time limit is used only if `<output parameter>` points to `ZUI` hash field, e.g. `ZUI[text_mode]`. Otherwise, the configuration is always read regardless of the time limit. `<variable>` should have `b:` prefix for boolean type, `s:` for string type (`s:` is the default). Boolean variables are mapped to just `0` or `1`, the same only values are accepted as `<default>` values for that variable type. Example call:

```zsh
-zui_std_load_config s:text_mode "off" 2 'ZUI[text_mode]'  # No text-segment navigation
```

The **Z style** variable is looked up at path `:plugin:zui`, then at `:plugin:zui:app:${ZUI[app]}`. The latter path has higher priority.

---

#### -zui_std_store_default_app_config

```zsh
-zui_std_store_default_app_config <variable> <value>
```

Stores gave variable to Zstyle **if** the variable is not already set. Can be used to set up the default configuration of the application. The user will be still able to set his configuration, the function will not overwrite it. Example call:

```zsh
-zui_std_store_default_app_config b:top_anchors 0  # No top-anchors
```

---

#### -zui_std_cleanup

```zsh
-zui_std_cleanup [serialize|deserialize:"app"]
```

Clears the `ZUI` hash – all configuration fields, anchors, buttons, etc. Also, clears fields that start with `my_` – this is the provided namespace to use by applications. If `serialize` is given, will store `my_*` fields and `zui-list` state fields into a special `ZUI` field. It can be then retrieved by `deserialize:"app"` – the effect will be like if the application was never left.

---

#### -zui_std_set_mod_factor

```zsh
-zui_std_set_mod_factor <module index> <factor>
```

Sets how many instances of a module given by index should be generated (the module-factor).

---

#### -zui_std_get_mod_factor

```zsh
-zui_std_get_mod_factor <module index> [output parameter]
```

Gets several instances of a module given by index. Stores result in `REPLY`, or in other parameters specified by name.

---

#### -zui_std_load_global_index_and_size

```zsh
-zui_std_load_global_index_and_size <module index> <instance index> [output param1] [output param2]
```

Loads where a module is located (at which line in the document) and what size it has (how many lines it occupies). Stores to `REPLY` and `REPLY2` by default, or to specified parameters.

---

#### -zui_std_reset_replies

```zsh
-zui_std_reset_replies
```

Generators use parameters `reply`, `reply2`, `reply3`, `reply4`. This function clears them.

---

#### -zui_std_map_replies

```zsh
-zui_std_map_replies
```

Generator output should be mapped onto parameters:

```
mod${midx}_ice${iidx}_output
mod${midx}_ice${iidx}_size
mod${midx}_ice${iidx}_nonselectables
mod${midx}_ice${iidx}_hops
mod${midx}_ice${iidx}_anchors
```

This function does this. It should normally not be needed, `-zui_std_fly_mod_regen` does this automatically.

---

#### -zui_std_fly_mod_regen

```zsh
-zui_std_fly_mod_regen <module index> <instance index>
```

Schedules on-the-fly document-fragment update. This corresponds to DHTML, to doing `document.getElementById('...').innerHtml=...`. No list restart is required (no "page reload"). Arguments `<module index>` and `<instance index>` specify which module instance should be regenerated. The generator used to obtain new content is taken from `zui-event-loop` list (see `-zui_std_fly_array_refresh`) and depends only on `<module index>`. In other words, the same generator is used, the one normally assigned to the module instance.

---

#### -zui_std_fly_mod_regen_ext

```zsh
-zui_std_fly_mod_regen <generator> <module index> <instance index>
```

The same as `-zui_std_fly_mod_regen`, but uses alternate, specified generator-function.

---

#### -zui_std_fly_array_refresh

```zsh
-zui_std_fly_array_refresh <module index>
```

Submits on-the-fly array refresh. The given `<module index>` should point to an array ("a:" prefix at `zui-event-loop`). The array will be read again and pasted into a document replacing previous content. For example, in the history demo there is:

```zsh
zui-event-loop 1:demo_generator_A a:u-history 1:demo_generator_A
```

Second module (and 1st instance) is array `history` that is made unique (the `u-` prefix). You can refresh that content (document fragment) via:

```zsh
-zui_std_fly_array_refresh 2
```

## Utility Library

Standard Library contains functions to:

- automate toggle buttons,
- strip color codes from text,
- etc.

### Calls of Utilities Library

Below are descriptions of Utilities Library functions. Arguments in triangular brackets are mandatory, in square brackets – optional.

---

#### -zui_util_map_bools

```zsh
-zui_util_map_bools <expressions> <parameters> <true string> <false string>
```

Maps boolean values of expressions given in `$1` (string with entries separated by ';') to parameters given via names in `$2` (separated by ';'). For true, `<true string>` is assigned to corresponding parameter, `<false string>` for false. Example call:

```zsh
local color1 color2 color3
-zui_util_map_bools "1;[[ a = b ]];ZUI[text_select]" "color1;color2;color3" $red $white
```

Parameter `color1` will be set to `$red`, `color2` to `$white`, `color3` will be assigned depending on `$ZUI[text_select]` value. Use this to automate toggle buttons – highlight the buttons with one of two colors, depending on the state of a backend variable.

---

#### -zui_util_strip_codes

```zsh
-zui_util_strip_codes <text>
```

Strips formatting codes from the text in saves the result into parameter `REPLY`.

---

#### -zui_util_get_time

```zsh
-zui_util_get_time
REPLY="H:M time string"
```

Returns time in format `%H:%M`, via `datetime` module (fast) or `date` command as the fallback

---

#### -zui_util_get_datetime

```zsh
-zui_util_get_datetime
REPLY="Ymd_H.M.S date string"
```

Returns date and time. Uses `datetime` zsh module (fast) or `date` command as a fallback.

---

#### -zui_util_get_timestamp

```zsh
-zui_util_get_timestamp
REPLY={seconds}
```

Returns timestamp, via `datetime` module (fast) or `date` as a fallback.

---

#### -zui_util_has_default_color

```zsh
-zui_util_has_default_color
```

Returns true if the "default" color can be used with current `Zsh`/`zcurses`.

---

#### -zui_util_resolve_path

```zsh
-zui_util_resolve_path <current working directory> <file path>
reply[1]={dir-name}
reply[2]={base-name}
```

Resolves absolute path to file from `<current working directory>` and `<file path>`. Returns the path as two components, dir-name in `reply[1]`, base-name in `reply[2]`.

---

#### -zui_util_to_cmd_line

```zsh
-zui_util_to_cmd_line <text>
```

Puts given text on the command line - regardless of Zle being active or not

---

#### -zui_util_circular_next

```zsh
-zui_util_circular_next <base> <size>
REPLY={path}
```

Returns next file to write to in circular buffer set of file names `<base>.1` `<base>.2` ... `<base>.<size>`. The buffer is ordered according to modification time – the oldest file from the set is the returned one (so after writing the circular buffer updates). Files are located in `~/.config/zui/var/circular_buffers`.

---

#### -zui_util_circular_paths

```zsh
-zui_util_circular_paths <base>
reply=( {path1} {path2} ... )
```

Returns absolute file paths of the given circular buffer. The paths are ordered from most recent to least recent. No count is obtained, so all files are returned, even actually disabled by any used `<size>` (with `-zui_util_circular_next`).

### Callbacks

Many situations are solved by callbacks. This eases the API, you don't have to e.g. supply a

function name in a call but instead just define a function. Callback names follow scheme `-zui-standard-*-callback`. They are automatically cleared at cleanup (i.e. at `-zui_std_cleanup` call).

---

#### -zui-standard-timeout-callback

```zsh
-zui-standard-timeout-callback
```

Called when `$ZUI[timeout]` milliseconds pass without user input (the timeout defaults to `-1`, i.e. no timeout defined). No arguments and the return value is not checked. Redraw of the screen might be invoked by setting `$ZUI[timeout_update]` to `1`. Regeneration of module can be scheduled by invoking `-zui_std_fly_mod_regen`, this implies setting `$ZUI[timeout_update]`. `$ZUI[timeout]` is a Z style of the same name.

[zui-demo-timeout](https://github.com/z-shell/zui/blob/main/demos/zui-demo-timeout) covers this callback.

---

#### -zui-standard-text-select-callback

```zsh
-zui-standard-text-select-callback <type> <text>
```

Called when a text is selected. This is possible when Z style `text_select` is `1`. The Zstyle `text_mode` can be `off` – only whole lines can be then selected. `<type>` is then set to string `line`. If `text_mode` is `hyp`, then text segments at lines with hyperlinks can be selected. When it is `nohyp` then this applies to lines without hyperlinks. Value `all` allows the selection of text segments at all lines, with or without hyperlinks. If a text-segment is selected, `<type>` is set to string `segment`.

---

#### -zui-standard-global-anchors-callback

```zsh
-zui-standard-global-anchors-callback <id> <initial line> <module index> <instance index>
```

Invoked when a global-anchor is pressed. Global anchors are typically at the first line of the document, controlled by Zstyle `top_anchors`. First argument `<id>` is the ID of the anchor button, in format `aglobal_m<module-index>_i<instance-index>`. The second argument `<initial line>` is set to destination line used when creating the anchor –&nbsp;it might have been changed by dynamic updates to document, i.e. module-regeneration that shifts target lines up or down. `<module index>` and `<instance index>` specify to which module instance the anchor is jumping to.

---

#### -zui-standard-status-callback

```zsh
-zui-standard-status-callback 0 <selectable> <uniq> <search> <line> <segment>
-zui-standard-status-callback 1 <selectable> <uniq> <search> <line> <segment> ...
```

Called after each key-press and also when timeout-callback schedules document update –&nbsp;`$ZUI[timeout_update]` is then `1`. First argument can be `0` or `1` and it is the type of active segment –&nbsp;`0` is case: no-hyperlink-active. `<selectable>` **/** `<uniq>` **/** `<search>` are `0` or `1` and denote if current line is selectable **/** if uniq mode is enabled **/** if there is a search query entered. Arguments `<line>` and `<segment>` are current line and segment.

For variant with `1` in first argument, what follows is current-hyperlink decoded data. For anchors and buttons, it is (follows code to be used to read the input):

```zsh
local id="$7" data1="$8" data2="$9" data3="$10" data4="$11"
```

For text-fields, it is:

```zsh
local id="$7" width="$8" index="$9" text="$10" data1="$11" data2="$12" data3="$13"
```

For list-boxes, it is:

```zsh
local id="$7" width="$8" index="$9" options_text="$10" data1="$11" data2="$12" data3="$13"
```

You can test for `tfield` in ID of a text-field, and for `lbox` in ID of a list-box. These strings are prepended to the IDs that you use when creating those hyperlinks. You can then read the whole data as follows:

```zsh
local tpe="$1" selectable="$2" uniq="$3" search="$4" line="$5" segment="$6"
shift 6
[[ "$1" = *(tfield|lbox)* ]] && local id="$1" width="$2" index="$3" text="$4" data1="$5" data2="$6" data3="$7" ||
                                local id="$1" data1="$2" data2="$3" data3="$4" data4="$5"
```

The main function of the status callback is adding a message to the status window. It should return `1` and set array `reply` to add the message. For example:

```zsh
reply=( "My " "new " "message" )
return 1
```

Returning `0` means not updating the status window, and `reply` is then ignored.

### Zstyles

To change ZUI global default, invoke:

```zsh
zstyle ":plugin:zui" colorpair "white/black"
```

An application may override such default with its default. To change default per-application, invoke:

```zsh
zstyle ":plugin:zui:app:zui-demo-fly" colorpair "250/17"  # 256 colors – zsh >= 5.3; "default" color also from this version
```

Below is a complete list of available Zstyles with ZUI default values.

<APITable>

| ZStyle name | Default | Description |
| --- | --- | --- |
| "colorpair | "white/black" | Default text and background color. For Zsh >= 5.3, color "default" is available, it might be e.g. transparent (depends on terminal configuration) |
| border | "no" | No border around main window |
| border_cp | "yellow/black" | Border (and header) color |
| bold | "no" | No default bold |
| status_colorpair | "white/black" | The same as "colorpair", but for status window |
| status_border | "no" | No border around status window |
| status_border_cp | "green/black" | Border color of status window |
| status_bold | "no" | No default bold in status window |
| mark | "red reverse lineund" | String starting with one or two color names continued with combination of: reverse, underline, blink, bold, lineund, linerev. Last two underline, reverse whole active line. The rest mark active button. Uppercase color names are for background |
| altmark | "red reverse" | As "mark", but for terminals without underline support |
| mark2 | "yellow reverse" | The same as "mark", but for buttons with background color |
| altmark2 | "yellow reverse" | The same as "altmark", but for "mark2", i.e. mark for buttons with background color, on terminals with no underline support |
| status_size | 4 | Height of status window, including border (drawn or not) |
| status_pointer | "yes" | Show line indicating position in document |
| log_append | "above" | Put log messages on top of others. Also available: "below" |
| log_time_format | "[%H:%M] " | Display hour:minute time stamp. Set to "" to disable time stamp completely |
| log_index | "yes" | Show order number of log messages |
| log_size | "32" | How many log messages to keep in memory |
| top_anchors | "yes" | Show anchors to each module instance at top |
| log_colors | "white cyan yellow green cyan red magenta yellow blue" | The colors used for log messages. First two are for message's index and time stamp |
| select_mode | "no-restart" | What to do on non-hyperlink selection. Such selection will invoke text-select callback with segment or whole line passed as argument. Plus, it will set ZUI[line_selected] or ZUI[pure_text_selected]. If the Zstyle is set to "restart" then list restart will be performed. If set to "quit" then event loop will be exited, and REPLY will be set to line or segment. |
| text_mode | "all" | Navigate across each bit of text, not only hyperlinks. "hyp" – only at lines with hyperlinks, "nohyp" – only at lines with no hyperlinks, "off" - text-bit navigation fully turned off |
| text_select | "yes" | Allow selection on non-hyperlinks (full lines when text_mode is "off" or "hyp" – meaning text-bit mode fully turned off or enabled only for lines with hyperlinks, leaving text-only lines undivided) |
| timeout | "-1" | No calls to timeout callback. Denotes milliseconds. Minimum value is 200. Time is counted when there is no user input |
| palette | "black:red:green: yellow:blue:magenta: cyan:white" | 8-color palette used by ZUI. Default is normal ANSI palette. Can be changed to indexes of 256 colors (zsh >= 5.3)" |

</APITable>

All Zstyles are available in ZUI repository: [Zstyles](https://github.com/z-shell/zui/blob/main/docs/ZSTYLES.md)

### Example - Hello World

```shell
# Started from Zle or from the command line

-zui_std_cleanup deserialize:"zui-demo-hello-world"
-zui_std_init app:"zui-demo-hello-world" app_name:"ZUI Hello World"
emulate -LR zsh -o extendedglob -o typesetsilent -o warncreateglobal
-zui_std_init2 # after emulate -LR

-zui_std_store_default_app_config b:border 1

demo_generator_A() {
    local mod="$1" ice="$2"
    # Content, no hyper-links
    reply=( "Hello World from ${ZUI[YELLOW]}ZUI${ZUI[FMT_END]}! Module $mod, instance $ice." )
    # Non-selectable lines   Hops to jump with [ and ]   Local anchors
    reply2=( )               reply3=( 1 )                reply4=( )
}

## Start application ##
zui-event-loop 1:demo_generator_A

-zui_std_cleanup serialize
```

Other example which uses list-box: [zui-demo-list-box](https://github.com/z-shell/zui/blob/main/demos/zui-demo-list-boxes).

### ZUI Installation

**The plugin is "standalone"**, which means that only sourcing it is needed. So to install, unpack `zui` somewhere and add

```shell
source {where-zui-is}/zui.plugin.zsh
```

to `zshrc`.

If using a plugin manager, then `ZI` is recommended, but you can use any other too, and also install with `Oh My Zsh` (by copying a directory to `~/.oh-my-zsh/custom/plugins`).

#### ZUI - [ZI](https://github.com/z-shell/zi)

Add `zi load z-shell/zui` to your `.zshrc` file. ZI will handle the rest automatically the next time you start zsh. To update (i.e. to pull from origin) issue `zi update z-shell/zui`.