=========
 shellia
=========

-------------------------------------
library for interactive shell scripts
-------------------------------------

:Author: bernd.schumacher@hpe.com
:Date: 2020-08-07
:Copyright: Bernd Schumacher <bernd.schumacher@hpe.com> (2007-2020)
:License: GNU General Public License, version 3
:Version: 0.1
:Manual section: 1
:Manual group: shell library

SYNOPSIS
========

  *script.using.shellia* [**-i|-s|-m**] [**-d** *debug-runtime-config*] [**-a**] [--] [*script-specific-options*]

DESCRIPTION
===========

**shellia** is a library that allows to run shell scripts interactive and helps
to familiarize oneself with large shell scripts, find the cause of unexpected
behaviour in shell scripts, and run shell scripts silently, while checking
them **step** by **step**.

A *script.using.shellia* can be called with option **-i** to run in
**interactive-mode**.
This means that the user can start **steps** of the script.

If the *script.using.shellia* uses **check-mode**,
output and return values of internal **steps** are checked.
If something unexpected happens, the script can either stop or ask the user
what to do.

OPTIONS
=======

General options
---------------

**-i**
  use **interactive-mode**

**-s**
  be silent

**-m**
  minimal control

**-d** *debug-runtime-config*
  Turn **debug-mode** on from the beginning. You also may turn debug on and off
  while running in **interactive-mode**.

**-a**
  Use only ascii without colour in **interactive-mode** and **logging-mode**

EXAMPLE
=======

Be aware that the **step** sizes in the examples listed below are only
reasonable to demonstrate shellia features and for no other purpose.
Please read shellia(7) **NOTES**, to learn about a reasonable **step** size.

Basic features
--------------

On **debian** systems the following described script *hello_world* may be
found at */usr/share/doc/shellia/examples/hello_world*.

If called without option, it will just print the words *hello* and *world*::

  $ /usr/share/doc/shellia/examples/hello_world
  hello
  world

If called with option **-i**, you will have some interactive choices::

  $ /usr/share/doc/shellia/examples/hello_world -i
  === hello_world ===
  1 echo "hello"
  2 echo "world"
  c continue without questionsq quit
  ? [1]

Entering *1* would execute the first **step** and print the word *hello*.
Actually, because *1* is preselected as shown in the last line, just entering
*RETURN*, would do the same.
Step *2* is equivalent to **step** *1*.
After **step** *2* the preselection would change to *q*.
*q* means *quit* and can be pressed anytime to leave the current **step** level,
Which would leave the shell script in our case.
Instead of entering *1*, *2* and *q*, *c* could have been entered to continue
automatically.

A discussion of the source of this shell script can be found in shellia(3)
**Basic features**.

Interactive-mode
----------------

In **Basic features** all **steps** shown in **Interactive-mode**
have been at the same level.
In **Interactive-mode** muliple levels are supported.

On **debian** systems the following described script *hello_world_fun* may be
found at */usr/share/doc/shellia/examples/hello_world_fun*.

If called without **shellia** specific option, but with the name "Test User",
the output will be::

  $ /usr/share/doc/shellia/examples/hello_world_fun "Test User"
  hello Test User

If additionally called with option **-i**, you will have some interactive
choices::

  $ /usr/share/doc/shellia/examples/hello_world_fun -i -- "Test User"
  === hello_world_fun ===
  1 say_hello -i -- "Test User"
  i toggle -i flag
  q quit?
  [1]

Entering *i* turns **-i** on and off as shown above and in the next line::

  1 say_hello -- "Test User"

If we would press *1* while **-i** is off, the function *say_hello* would be
executed at once.
Pressing *1* while **-i** is on would start function *say_hello* in
**interactive-mode** and display the following menu with **steps** in a deeper
level::

  === hello_world_fun/say_hello ===
  1 name="Test User"
  2 echo "hello $name"
  c continue without questions
  q quit?
  [1]

In the heading we can see, the name of the current function.
Because we have to start with the first **step** in this function again *1* is
preselected.
To run all **steps** in this function we can press *c*. After executing,
we will return to the previous menu and can press *RETURN* to select
the preselected *quit*.

A discussion of the source of this shell script can be found in shellia(3)
**Interactive-mode**.

Debug-mode
----------

Each *debug-statement* in a *script-using-shellia* has additionally to the
**debug-output** a **debug-statement-level**, and a **debug-statement-topic**
with the defaults *1* and *none*.

At runtime the script gets a **debug-runtime-level** and a
**debug-runtime-topic** list with the defaults *0* and empty.

The **debug-output** will be shown if the, the **debug-runtime-level** is higher
or equal to the **debug-statement-level** and either the
**debug-statement-topic** is in the **debug-runtime-topic** list, or
the **debug-runtime-topic** list is empty.

On **debian** systems the example script *hello_world_debug* may be
found at */usr/share/doc/shellia/examples/hello_world_debug*.

In the header of the script we can read, that the used **debug-topics** are
*none*, *start* and *end* and that the higest **debug-level** is 3.

To see all **debug-output** we can start with an empty
**debug-runtime-topic** list and the very high **debug-runtime-level** *99*::

  $ /usr/share/doc/shellia/examples/hello_world_debug -d 99
  DEBUG main program
  DEBUG say_hello function start
  hello world
  DEBUG say_hello function end

To see only the **debug-topics** *none* and *start* in **interactive-mode**
we can call::

  $ /usr/share/doc/shellia/examples/hello_world_debug -d "99 none start"
  === hello_world_debug ===
  1 dbg "main program"
  2 say_hello_world
  d ... change dbg: 99 none start
  c continue without questions
  q quit
  ? [1]

If we now change our mind, to not see the **debug-topic** *start* anymore and
to change the  **debug-level** *2* we can change this by entering *d start 2*
before continuing with *c*::

  ? [1] d start 2
  === hello_world_debug ===
  1 dbg "main program"
  2 say_hello_world
  d ... change dbg: 2 none
  c continue without questions
  q quit
  ? [1] c
  DEBUG main program
  hello world

The **interactive-mode** can be used to turn on **debug-output** only in **steps**
where we need it.

Log-mode
--------

If the *script-using-shellia* creates a logfile as described in shellia(3)
**logfile-mode**, the created logfile has some features as shown in the
example script *hello_world_log*.
On **debian** systems it may be
found at */usr/share/doc/shellia/examples/hello_world_log*.
The example script will automatically display the logfile at the end.

First we call it without options::

  $ /usr/share/doc/shellia/examples/hello_world_log "shellia user"
  hello shellia user
  --- LOGFILE ---
  |hello_world_log
  ||hello_world_log/say_hello
  ||s:hello shellia user
  ---------------

The first line shows how the script is called.
The second line shows the output of the script *hello shellia user*
Then the logfile is displayed in two lines starting with dashes.
The first line of the logfile has one bar, indicating that we are in the
first level, which is the main script in file  *hello_world_log*
The second line of the logfile has two bars, indicating we are in the
next level, followed by the filename and the function name.
The third line is from the same function and show with an *s:*, that
stdout *hello shellia user* has been created by this function.

We will now run the same script with all debug output enabled
to see debug information with the word *DEBUG* added ::

  $ /usr/share/doc/shellia/examples/hello_world_log -d 99 "shellia user"
  DEBUG main program begin
  DEBUG function say_hello called with 1 arguments
  hello shellia user
  DEBUG function say_hello end
  DEBUG main program end
  --- LOGFILE ---
  |hello_world_log
  |DEBUG main program begin
  ||hello_world_log/say_hello
  ||DEBUG function say_hello called with 1 arguments
  ||s:hello shellia user
  ||DEBUG function say_hello end
  |DEBUG main program end
  ---------------

Another way is to start in interactive mode, manually select the function with
*2*, continue all steps in the function with *c* and then quit with *q*.
Now also the interactive input and output will be logged and the logfile
will be too large, to display it here.

variable in Interactive-mode
----------------------------

If you see *$<var>* in interactive mode, the meaning is like *\\${var}*,
but you can press **v** to see the actual value of the variable.
If you press **v** again, the name of the variable is shown as before.

NOTES
=====
**shellia** is tested successful with *bash*, *dash*, *busybox sh*, *mksh* and
*posh*.
To use **shellia** with *posh* the nounset option (*set -o nounset* or
*set -u*) is not supported because of Bug #913718 (posh can not use "$@"
together with set -u). Because of Bug #910275 (posh does never execute an
"EXIT trap", if it is created with the "trap" command in a sub shell) remaining
files named "/tmp/shellia.??????????" should be deleted manual, after using
**shellia** with *posh*.
**shellia** can not be used in *ksh*, because the shell does not support the
*local* command.

error messages
==============

**ERROR: ia premature exit of** *command*
**unchecked output:** *unchecked output*

     Before output of a *command* issued with **check-mode** can be printed, it
     will be collected and checked. If the *script.using.shellia* exits premature,
     the already collected *unchecked output* is printed with this error message.

SEE ALSO
========

shellia(3), shellia(7)
