HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/magento.bikenow.co/vendor/hoa/console/Documentation/En/Index.xyl
<?xml version="1.0" encoding="utf-8"?>

<overlay xmlns="http://hoa-project.net/xyl/xylophone">
<yield id="chapter">

  <p>The terminal is a very <strong>powerful interface</strong> that is based on
  multiple concepts. <code>Hoa\Console</code> allows to write
  <strong>tools</strong> that are adapted to this kind of environment.</p>

  <h2 id="Table_of_contents">Table of contents</h2>

  <tableofcontents id="main-toc" />

  <h2 id="Introduction" for="main-toc">Introduction</h2>

  <p>Nowadays, we have two kinds of interface: <strong>textual</strong> and
  <strong>graphical</strong>. The textual interface exist since the origin of
  computers, then called terminal. This interface, despite its “raw” aspect, is
  functionally very <strong>powerful</strong> thanks to several concepts such as
  the readline or pipes. Today, it is even more used because it is often faster
  than a graphical interface when executing <strong>complex</strong> tasks. It
  can also easily be used through networks or on a machine with low
  performances. In short, this interface is still
  <strong>indispensable</strong>.</p>
  <p>From the user point of view, there is three levels to consider:</p>
  <ul>
    <li>the <strong>interface</strong>: print and edit text, manipulate the
    window, the cursor etc.,</li>
    <li>the <strong>program</strong>: interact with the user with a maximum of
    comfort, use the readline as much better as possible, build programs adapted
    to this kind of interface,</li>
    <li>the <strong>interaction</strong> with other programs: automatically
    interact and communicate with other programs.</li>
  </ul>
  <p>The <code>Hoa\Console</code> library provides tools to answer to these
  three levels. Thus, it is based on standards, such as
  <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf">ECMA-48</a>
  that specifies the communication with the system through sequences of ASCII
  characters and control codes (also called escaping sequences), all of that, in
  order to manipulate the window, the cursor or other devices of the machine.
  Other features are also standard such as the way we read options from a
  program, very <strong>inspired</strong> of systems like
  <a href="http://linux.org/">Linux</a>, <a href="http://freebsd.org/">FreeBSD</a>
  or <a href="https://en.wikipedia.org/wiki/UNIX_System_V">System V</a>. By the
  way, if you are familiar with several C libraries, you will not be lost. And
  <em>a contrario</em>, if you learn to use <code>Hoa\Console</code>, you will
  not be lost when using low-level languages such as C.</p>
  <p>Before starting, we would like to add a little note
  <strong>only</strong> about the window and cursor support. Today, we have the
  choice among <strong>many</strong> terminals per system and some of them are
  more comprehensive than others. For example,
  <a href="https://windows.microsoft.com/">Windows</a> and its default terminal,
  <a href="http://en.wikipedia.org/wiki/MS-DOS">MS-DOS</a>, does not respect any
  standard. In this case, forget the ECMA-48 standard and take a look at
  <a href="http://msdn.microsoft.com/library/ms682087.aspx"
     title="Console Reference">the <code>Wincon</code> library</a>. It is often
  recommended to use a <strong>virtual</strong> Unix machine or a terminal
  <strong>emulator</strong>, such as
  <a href="http://ttssh2.sourceforge.jp/">TeraTerm</a>, very comprehensive. Even
  on systems that are closed to the BSD family, the embeded terminals do not
  support all the standards. This is the case of Mac OS X where we recommend to
  use <a href="http://iterm2.com">iTerm2</a> instead of Terminal. Finally, on
  other systems of the Linux or BSD family, we recommend
  <a href="http://software.schmorp.de/pkg/rxvt-unicode.html">urxvt</a>. For
  other features, such as the readline, the options reading, the processus etc.,
  <code>Hoa\Console</code> is perfectly <strong>compatible</strong> and
  suitable.</p>

  <h2 id="Window" for="main-toc">Window</h2>

  <p>The window of a terminal must be understood as a <strong>canvas</strong> of
  <strong>columns</strong> and <strong>lines</strong>. The
  <code>Hoa\Console\Window</code> allows to manipulate the
  <strong>window</strong> of a terminal and its <strong>content</strong> through
  static methods.</p>

  <h3 id="Size_and_position" for="main-toc">Size and position</h3>

  <p>The first elementary operations are about the <strong>size</strong> and the
  <strong>position</strong> of the window, thanks to the <code>setSize</code>,
  <code>getSize</code>, <code>moveTo</code> and <code>getPosition</code>
  methods. The size is defined with the <em>column</em> × <em>line</em> unit and
  the position is defined in pixels. Thus:</p>
  <pre><code class="language-php">Hoa\Console\Window::setSize(80, 50);
print_r(Hoa\Console\Window::getSize());
print_r(Hoa\Console\Window::getPosition());

/**
 * Will output:
 *     Array
 *     (
 *         [x] => 80
 *         [y] => 50
 *     )
 *     Array
 *     (
 *         [x] => 104
 *         [y] => 175
 *     )
 */</code></pre>
  <p>We will notice that the window is resized <strong>itself</strong>. Nor the
  size or the position of the window is stored in memory, they are computed at
  each call of the <code>getSize</code> and <code>getPosition</code> method.
  Attention, the <em>y</em> axe of the window position is computed from the
  <strong>bottom</strong> of the screen and not from the top of the screen as we
  might expect!</p>
  <p>It is also possible to listen the
  <code>hoa://Event/Console/Window:resize</code> <strong>event</strong> that is
  fired each time the window is resized: either manually or with the
  <code>setSize</code> method. We need two things in order to see this event
  working:</p>
  <ol>
    <li><a href="http://php.net/pcntl">the <code>pcntl</code> extension</a> must
    be activated,</li>
    <li>we have to use <a href="http://php.net/declare">the <code>declare</code>
    structure</a> to enable the <a href="http://php.net/pcntl_signal">the
    <code>pcntl_signal</code> function</a>.</li>
  </ol>
  <p>To put the program in a passive waiting state, we will use
  <a href="http://php.net/stream_select">the <code>stream_select</code>
  function</a>, this is a <strong>detail</strong>, only present to test our
  code, else the program will terminate directly. Thus:</p>
  <pre><code class="language-php">Consistency\Autoloader::load('Hoa\Console\Window'); // make sure it is loaded.

declare(ticks = 1);

Hoa\Event\Event::getEvent('hoa://Event/Console/Window:resize')
    ->attach(function (Hoa\Event\Bucket $bucket) {
        $data = $bucket->getData();
        $size = $data['size'];

        echo 'New size (', $size['x'], ', ', $size['y'], ')', "\n";
    });

// Passive loop.
while (true) {
    $r = [STDIN];
    @stream_select($r, $w, $e, 3600);
}</code></pre>
  <p>When we modify the size of the window, we will see for example:
  <code>New size (45, 67)</code>, and this, for each resize. This event is
  interesting if we would like to <strong>re-layout</strong> our view.</p>
  <p>Finally, we can minimize or restore the window thanks to the
  <code>Hoa\Console\Window::minimize</code> and
  <code>Hoa\Console\Window::restore</code> static methods. Moreover, we can put
  the window in the background (behind all other windows) thanks to the
  <code>Hoa\Console\Window::lower</code> static method, just like we can place
  it in the foreground with <code>Hoa\Console\Window::raise</code>. For
  example:</p>
  <pre><code class="language-php">Hoa\Console\Window::minimize();
sleep(2);
Hoa\Console\Window::restore();
sleep(2);
Hoa\Console\Window::lower();
sleep(2);
Hoa\Console\Window::raise();

echo 'Back!', "\n";</code></pre>

  <h3 id="Title_and_label" for="main-toc">Title and label</h3>

  <p>The <strong>title</strong> of a window is the text displayed in the top
  <strong>bar</strong> in which the controls of the window are often placed,
  such as the maximization, the minimization etc. The <strong>label</strong> is
  the name associated to the current <strong>processus</strong>. We have the
  <code>setTitle</code>, <code>getTitle</code> and <code>getLabel</code>
  methods, it is not possible to modify the label. To define the title of the
  processus (what we see with the <code>top</code> or <code>ps</code> command
  for example), we must take a look at
  <code>Hoa\Console\Processus::setTitle</code> and also at
  <code>Hoa\Console\Processus::getTitle</code> to get it. Thus:</p>
  <pre><code class="language-php">Hoa\Console\Window::setTitle('Foobar');
var_dump(Hoa\Console\Window::getTitle());
var_dump(Hoa\Console\Window::getLabel());

/**
 * Will output:
 *     string(6) "Foobar"
 *     string(3) "php"
 */</code></pre>
  <p>Once again, the title and the label are not stored in memory, they are
  computed at each call of the methods.</p>

  <h3 id="Interact_with_the_content" for="main-toc">Interact with the
  content</h3>

  <p><code>Hoa\Console\Window</code> also allows to control the
  <strong>content</strong> of the window, or at least the viewport, it means the
  <strong>visible</strong> content of the window. Only one method is available:
  <code>scroll</code>, that allows to <strong>move</strong> the content to the
  top or the bottom. The arguments of this method are very simple:
  <code>up</code> or <code>↑</code> to move up of one line and <code>down</code>
  or <code>↓</code> to move down of one line. We are able to concatenate those
  directions by a space or to repeat one direction:</p>
  <pre><code class="language-php">Hoa\Console\Window::scroll('↑', 10);</code></pre>
  <p>In reality, this method will move the content in order to get <em>x</em>
  new lines respectively bellow or above the cursor. Attention, the cursor
  <strong>does not move</strong>!</p>
  <p>Even if it is most of the time useless, it is possible to
  <strong>refresh</strong> the window, it means to redo a full render. We can
  use the <code>refresh</code> method, still on
  <code>Hoa\Console\Window</code>.</p>
  <p>Finally, it is possible to put a text inside the <strong>clipboard</strong>
  of the user thanks to the <code>copy</code> method:</p>
  <pre><code class="language-php">Hoa\Console\Window::copy('Foobar');</code></pre>
  <p>Then, if the user pastes what is in the clipboard, she will see
  <code>Foobar</code>.</p>

  <h2 id="Cursor" for="main-toc">Cursor</h2>

  <p>Inside a window, we have a cursor that can be seen as a tip of pen. The
  <code>Hoa\Console\Cursor</code> class allows to manipulate the
  <strong>cursor</strong> of the terminal through static methods.</p>

  <h3 id="Moving" for="main-toc">Moving</h3>

  <p>We will start to <strong>move</strong> the cursor. It can move everywhere
  inside the viewport, it means the <strong>visible</strong> content of the
  terminal window, but we will write a piece of text and move around at first.
  The <code>move</code> method on <code>Hoa\Console\Cursor</code> allows to move
  the cursor in several <strong>directions</strong>. First of all,
  relatively:</p>
  <ul>
    <li><code>u[p]</code> or <code>↑</code>, to move the cursor one line
    above,</li>
    <li><code>r[ight]</code> or <code>→</code>, to move the cursor on the next
    column,</li>
    <li><code>d[own]</code> or <code>↓</code>, to move the cursor one line
    bellow,</li>
    <li><code>l[eft]</code> or <code>←</code>, to move the cursor on the
    previous column.</li>
  </ul>
  <p>We also have <strong>semi-absolute</strong> moving:</p>
  <ul>
    <li><code>U[P]</code>, to move the cursor on the first line of the
    viewport,</li>
    <li><code>R[IGHT]</code>, to move the cursor on the last column of the
    viewport,</li>
    <li><code>D[OWN]</code>, to move the cursor on the last line of the
    viewport,</li>
    <li><code>L[EFT]</code>, to move the cursor on the first column of the
    viewport.</li>
  </ul>
  <p>We are able to concatenate those directions by a space or to repeat one
  direction.</p>
  <pre><code class="language-php">echo
    'abcdef', "\n",
    'ghijkl', "\n",
    'mnopqr', "\n",
    'stuvwx';

sleep(1);
Hoa\Console\Cursor::move('↑');
sleep(1);
Hoa\Console\Cursor::move('↑ ←');
sleep(1);
Hoa\Console\Cursor::move('←', 3);
sleep(1);
Hoa\Console\Cursor::move('DOWN');
sleep(1);
Hoa\Console\Cursor::move('→', 4);</code></pre>
  <p>During the execution, we will see the cursor moving <strong>by
  itself</strong> from a letter to another one each second.</p>
  <p>To actually move the cursor in an <strong>absolute</strong> way, we will
  use the <code>moveTo</code> method that takes <em>column</em> × <em>line</em>
  coordinates (starting from 1 and not 0) as argument. Similarly, there is the
  <code>getPosition</code> method that returns the <strong>position</strong> of
  the cursor. Thus, if we would like to move the cursor from the column 12 and
  line 7, and then print its coordinates, we will write:</p>
  <pre><code class="language-php">Hoa\Console\Cursor::moveTo(12, 7);
print_r(Hoa\Console\Cursor::getPosition());

/**
 * Will output:
 *     Array(
 *         [x] => 12
 *         [y] => 7
 *     )
 */</code></pre>
  <p>Finally, we often would like to move the cursor <strong>temporary</strong>
  for some operations. In this case, it is useless to get its current position,
  to move it and then re-position it; we can benefit from the <code>save</code>
  and <code>restore</code> methods. As their names suggest, they respectively
  <strong>save</strong> the position of the cursor and then
  <strong>restore</strong> the cursor as the previously saved position. These
  functions do not manipulate a <strong>stack</strong>, it is impossible to save
  more than one position at a time (the new record will <strong>erase</strong>
  the previous one). Thus, we will write a text, save the position of the
  cursor, go back to rewrite, and then go back to our previous position:</p>
  <pre><code class="language-php">echo 'hello world';

// Save cursor position.
Hoa\Console\Cursor::save();
sleep(1);

// Go to the begining of the line.
Hoa\Console\Cursor::move('LEFT');
sleep(1);

// Replace “h” by “H”.
echo 'H';
sleep(1);

// Go to “w”.
Hoa\Console\Cursor::move('→', 5);
sleep(1);

// Replace “w” by “W”.
echo 'W';
sleep(1);

// Back to the saved position.
Hoa\Console\Cursor::restore();
sleep(1);

echo '!';</code></pre>
  <p>The final result will be <code>Hello World!</code>. We can notice that each
  time a character is written, the cursor <strong>moves</strong>.</p>

  <h3 id="Content" for="main-toc">Content</h3>

  <p>Now we know how to move, we will see how to <strong>clean</strong> some
  lines and/or columns. We will use the <code>clean</code> method that takes the
  following symbols (concatenated by a space) as argument:</p>
  <ul>
    <li><code>a[ll]</code> or <code>↕</code>, to clean all the screen and move
    the cursor in the top-left corner of the viewport,</li>
    <li><code>u[p]</code> or <code>↑</code>, to clean all the lines above the
    cursor,</li>
    <li><code>r[ight]</code> or <code>→</code>, to clean the rest of the line
    from the cursor,</li>
    <li><code>d[own]</code> or <code>↓</code>, to clean all the lines bellow the
    cursor,</li>
    <li><code>l[eft]</code> or <code>←</code>, to clean the line from its
    beginning to the cursor,</li>
    <li><code>line</code> or <code>↔</code>, to clean all the line and move the
    cursor to its beginning.</li>
  </ul>
  <p>Thus, to clean <strong>a line</strong>:</p>
  <pre><code class="language-php">Hoa\Console\Cursor::clear('↔');</code></pre>
  <p>The cursor can act as a brush and thus write in different
  <strong>colors</strong> or different <strong>styles</strong> thanks to the
  <code>colorize</code> method (we can mix everything by separating each
  “command” by spaces). We start by enumerating all the styles:</p>
  <ul>
    <li><code>n[ormal]</code>, to cancel all applied styles,</li>
    <li><code>b[old]</code>, to write in bold,</li>
    <li><code>u[nderlined]</code>, to get an underlined text,</li>
    <li><code>bl[ink]</code>, to get a blinking text,</li>
    <li><code>i[nverse]</code>, to reverse colors of the foreground and the
    background,</li>
    <li><code>!b[old]</code>, to cancel the bold,</li>
    <li><code>!u[nderlined]</code>, to cancel the underline,</li>
    <li><code>!bl[ink]</code>, to cancel the blink,</li>
    <li><code>!i[nverse]</code>, to no longer reverse colors of the foreground
    and the background.</li>
  </ul>
  <p>Those styles are very classical. Now, let's see the colors. Before all, we
  have to say if we apply a color on the <strong>foreground</strong> of the
  text (the text itself) or on the <strong>background</strong>. Then, we will
  respectively use the <code>f[ore]g[round](<em>color</em>)</code> or
  <code>b[ack]g[round](<em>color</em>)</code> syntax. The value of
  <code><em>color</em></code> can be:</p>
  <ul>
    <li><code>default</code>, to get the default color of the ground,</li>
    <li><code>black</code>, <code>red</code>, <code>green</code>,
    <code>yellow</code>, <code>blue</code>, <code>magenta</code>,
    <code>cyan</code> or <code>white</code>,</li>
    <li>a number between <code>0</code> and <code>256</code>, representing the
    number of the color in the 256 colors palette,</li>
    <li><code>#<em>rrggbb</em></code> where <code><em>rrggbb</em></code> is the
    hexadecimal number representing the number of the color in the
    2<sup>64</sup> colors palette.</li>
  </ul>
  <p>Terminals manipulate <strong>one</strong> of two palettes: 8 colors or 256
  colors. Each color is <strong>indexed</strong> starting from 0. The names of
  colors are <strong>transformed</strong> into their respective index. When a
  color is given in hexadecimal, the <strong>closest</strong> color in the 256
  colors palette is used.</p>
  <p>Thus, if we would like to write <code>Hello</code> in yellow on a red-like
  background (<code>#932e2e</code>) and underlined, then <code> world</code> but
  not underlined:</p>
  <pre><code class="language-php">Hoa\Console\Cursor::colorize('fg(yellow) bg(#932e2e) underlined');
echo 'Hello';
Hoa\Console\Cursor::colorize('!underlined');
echo ' world';</code></pre>
  <p>Finally, it is possible to modify the palette of colors thanks to the
  <code>changeColor</code> method, but use it with <strong>caution</strong>,
  this can disturb the user. This method takes as first argument the index of
  the color and as second argument its hexadecimal value. For example,
  <code>fg(yellow)</code> matches the <code>33</code> index, and we would like
  to see it blue:</p>
  <pre><code class="language-php">Hoa\Console\Cursor::changeColor(33, 0xf00);</code></pre>
  <p>However, the 256 colors palette is <strong>wide</strong> enough to not need
  to redefine colors.</p>

  <h3 id="Style" for="main-toc">Style</h3>

  <p>The cursor is not necessary visible. During some operations, we can
  <strong>hide</strong> it, make some moves and then make it
  <strong>visible</strong> again. The <code>hide</code> and <code>show</code>
  methods, still on <code>Hoa\Console\Cursor</code>, are here for that:</p>
  <pre><code class="language-php">echo 'Visible', "\n";
sleep(5);

echo 'Invisible', "\n";
Hoa\Console\Cursor::hide();
sleep(5);

echo 'Visible', "\n";
Hoa\Console\Cursor::show();
sleep(5);</code></pre>
  <p>There is three <strong>types</strong> of cursors, that we will choose with
  the <code>setStyle</code> method:</p>
  <ul>
    <li><code>b[lock]</code> or <code>▋</code>, to get a cursor represented by a
    block,</li>
    <li><code>u[nderline]</code> or <code>_</code>, to get a cursor represented
    by an underscore,</li>
    <li><code>v[ertical]</code> or <code>|</code>, to get a cursor represented
    by a pipe.</li>
  </ul>
  <p>This method takes as a second argument a boolean which indicates if the
  cursor must <strong>blink</strong> (default value) or not. Thus, we will try
  all the styles:</p>
  <pre><code class="language-php">echo 'Block/steady: ';
Hoa\Console\Cursor::setStyle('▋', false);
sleep(3);

echo "\n", 'Vertical/blink: ';
Hoa\Console\Cursor::setStyle('|', true);
sleep(3);

// etc.</code></pre>
  <p>The cursor often indicates <strong>area</strong> or
  <strong>interactive</strong> elements, just like the pointer of a mouse.</p>

  <h3 id="Sound" for="main-toc">Sound</h3>

  <p>The cursor is also able to emit a little “bip”, most of the time to
  <strong>bring</strong> the attention of the user. We will use the eponym
  <code>bip</code> method:</p>
  <pre><code class="language-php">Hoa\Console\Cursor::bip();</code></pre>
  <p>There is only one available <strong>tonality</strong>.</p>

  <h2 id="Readline" for="main-toc">Readline</h2>

  <p>A way to <strong>interact</strong> with users is to read the
  <code>STDIN</code> stream, namely the input stream. This
  <strong>reading</strong> is by default very basic: unable to erase, unable to
  use arrows, unable to use shortcuts etc. That's why there is the readline,
  that is still a reading on the <code>STDIN</code> stream, but more
  <strong>sophisticated</strong>. The <code>Hoa\Console\Readline\Readline</code>
  library provides several features that we will describe.</p>

  <h3 id="Basic_usage" for="main-toc">Basic usage</h3>

  <p>To <strong>read a line</strong> (it means an input from the user), we will
  instanciate the <code>Hoa\Console\Readline\Readline</code> class and call the
  <code>readLine</code> method. Each call of this method will wait that the user
  <strong>inputs</strong> a data and then hits <kbd title="Enter">↵</kbd>. At
  this moment, the method will returns the input from the user (or
  <code>false</code> if there is nothing to read). This method also takes a
  <strong>prefix</strong> as argument, it means a data to print before the line.
  Sometimes, the term <em>prompt</em> could be used in the literature, both
  notions are identical.</p>
  <p>Thus, we will write a program that will read the inputs from the user and
  make an echo. The program will finish if the user inputs
  <code>quit</code>:</p>
  <pre><code class="language-php">$rl = new Hoa\Console\Readline\Readline();

do {
    $line = $rl->readLine('> ');
    echo '&amp;lt; ', $line, "\n\n";
} while (false !== $line &amp;amp;&amp;amp; 'quit' !== $line);</code></pre>
  <p>Now, let's detail the features offered by
  <code>Hoa\Console\Readline\Readline</code>.</p>
  <p>We are able to <strong>move</strong> (understand, move the cursor) in the
  line with the help of the <kbd>←</kbd> and <kbd>→</kbd> keys. We can
  <strong>erase</strong> a character back at any moment with the
  <kbd title="Backspace">⌫</kbd> key or all the characters until the beginning
  of the word with <kbd>Ctrl</kbd> + <kbd>W</kbd> (where <kbd>W</kbd> stands for
  word). We are also able to move the cursor by using <strong>shortcuts</strong>
  that a shared by many softwares:</p>
  <ul>
    <li><kbd>Ctrl</kbd> + <kbd>A</kbd>, to move at the beginning of the
    line,</li>
    <li><kbd>Ctrl</kbd> + <kbd>E</kbd>, to move at the end of the line,</li>
    <li><kbd>Ctrl</kbd> + <kbd>B</kbd>, to move at the beginning of the current
    word (<kbd>B</kbd> stands for backward),</li>
    <li><kbd>Ctrl</kbd> + <kbd>F</kbd>, to move at the end of the current word
    (<kbd>F</kbd> stands for forward).</li>
  </ul>
  <p>We also have access to the <strong>history</strong> when we hit the
  <kbd>↑</kbd> and <kbd>↓</kbd> keys, respectively to search back and forth in
  the history. The <kbd title="Tabulation">⇥</kbd> key fires the
  <strong>auto-completion</strong> if set. And finally, the
  <kbd title="Enter">↵</kbd> key returns the input.</p>
  <p>There is also the <code>Hoa\Console\Readline\Password</code> class that
  allows to have a readline with the same features but the characters
  <strong>are not printed</strong> to the screen, very useful to read a
  <strong>password</strong>:</p>
  <pre><code class="language-php">$rl  = new Hoa\Console\Readline\Password();
$pwd = $rl->readLine('Password: ');

echo 'Your password is: ', $pwd, "\n";</code></pre>

  <h3 id="Shortcuts" for="main-toc">Shortcuts</h3>

  <p>To understand how to create a shortcut, we have to understand a little bit
  how the <code>Hoa\Console\Readline\Readline</code> class works
  <strong>internally</strong>, and this is very simple. Each time we hit one or
  many keys, a <strong>string</strong> representing this
  <strong>combination</strong> is received by our readline. It looks for an
  associated action to this string: if one exists, then this one will be
  executed, else the readline will use a default action consisting to print the
  string verbatim. Each action returns the <strong>state</strong> of the
  readline (which are constants on
  <code>Hoa\Console\Readline\Readline</code>):</p>
  <ul>
    <li><code>STATE_CONTINUE</code>, to continue the reading,</li>
    <li><code>STATE_BREAK</code>, to stop the reading,</li>
    <li><code>STATE_NO_ECHO</code>, to not print the reading.</li>
  </ul>
  <p>Thus, if an action returns <code class="language-php">STATE_CONTINUE |
  STATE_NO_ECHO</code>, the reading will continue but the string that has been
  received will not be printed. Another example, the action associated to the
  <kbd title="Enter">↵</kbd> key returns the <code>STATE_BREAK</code> state.</p>
  <p>To <strong>add</strong> actions, we use the <code>addMapping</code> method.
  This latter eases the add thanks to a dedicated syntax:</p>
  <ul>
    <li><code>\e[<em>…</em></code>, for sequences starting by the <kbd>Esc</kbd>
    character,</li>
    <li><code>\C-<em>…</em></code>, for sequences starting by the
    <kbd>Ctrl</kbd> character,</li>
    <li><code><em>x</em></code>, any character.</li>
  </ul>
  <p>For example, if we would like to print <code>z</code> instead of
  <code>a</code>, we will write:</p>
  <pre><code class="language-php">$rl->addMapping('a', 'z');</code></pre>
  <p>More sophisticated this time, we can use a callable as the second argument
  of the <code>addMapping</code> method. This callable will receive the instance
  of <code>Hoa\Console\Readline\Readline</code> as the only argument. Several
  methods will help to <strong>manipulate</strong> the reading (to manage the
  history, the line etc.). For example, each time we will hit
  <kbd>Ctrl</kbd> + <kbd>R</kbd>, we will reverse the case of the line:</p>
  <pre><code class="language-php">$rl = new Hoa\Console\Readline\Readline();

// Add mapping.
$rl->addMapping('\C-R', function (Hoa\Console\Readline\Readline $self) {
    // Clear the line.
    Hoa\Console\Cursor::clear('↔');
    echo $self->getPrefix();

    // Get the line text.
    $line = $self->getLine();

    // New line.
    $new  = null;

    // Loop over all characters.
    for ($i = 0, $max = $self->getLineLength(); $i &amp;lt; $max; ++$i) {
        $char = mb_substr($line, $i, 1);

        if ($char === $lower = mb_strtolower($char)) {
            $new .= mb_strtoupper($char);
        } else {
            $new .= $lower;
        }
    }

    // Set the new line.
    $self->setLine($new);

    // Set the buffer (and let the readline echoes or not).
    $self->setBuffer($new);

    // The readline will continue to read.
    return $self::STATE_CONTINUE;
});

// Try!
var_dump($rl->readLine('> '));</code></pre>
  <p>Do not hesitate to take a look at how previous listed shortcuts have been
  implemented to get ideas.</p>

  <h3 id="Auto-completion" for="main-toc">Auto-completion</h3>

  <p>Another very useful tool when we are writing a readline is the
  <strong>auto-completion</strong>. It is fired when hiting the
  <kbd title="Tabulation">⇥</kbd> key if the auto-completer has been defined
  with the <code>setAutocompleter</code> method.</p>
  <p>All the auto-completers must implement the
  <code>Hoa\Console\Readline\Autocompleter\Autocompleter</code> interface. Some
  of them are already distributed to <strong>help</strong> us in our
  development, such as <code>Hoa\Console\Readline\Autocompleter\Word</code> that
  will auto-complete the input based on a <strong>list of words</strong>. For
  example:</p>
  <pre><code class="language-php">$rl = new Hoa\Console\Readline\Readline();
$rl->setAutocompleter(new Hoa\Console\Readline\Autocompleter\Word([
    'hoa',
    'console',
    'readline',
    'autocompleter',
    'autocompletion',
    'password',
    'awesome'
]));
var_dump($rl->readLine('> '));</code></pre>
  <p>Let's try to write something, then where we would like, we hit
  <kbd title="Tabulation">⇥</kbd>. If the text at the left of the cursor starts
  by <code>h</code>, then we will see <code>hoa</code> <strong>printed</strong>
  in the line because the auto-completer has no choice (it returns a string). If
  the auto-completer does not find any appropriated word,
  <strong>nothing</strong> will happen (it will return <code>null</code>). And
  finally, if it finds <strong>several words</strong> (it will return an array),
  then a <strong>menu</strong> will appear. Let's try to simply auto-complete
  <code>a</code>: the menu will propose <code>autocompleter</code>,
  <code>autocompletion</code> and <code>awesome</code>. Either we continue to
  hit and the menu will <strong>disappear</strong>, or we can
  <strong>move</strong> the cursor inside the menu with the
  <kbd title="Tabulation">⇥</kbd>, <kbd>↑</kbd>, <kbd>→</kbd>, <kbd>↓</kbd> and
  <kbd>←</kbd> keys, then <kbd title="Enter">↵</kbd> to <strong>select</strong>
  a word. This behavior is quite <strong>natural</strong>.</p>
  <p>In addition to the auto-completer on words, we find the auto-completer on
  <strong>paths</strong> with the
  <code>Hoa\Console\Readline\Autocompleter\Path</code> class. Based on a root
  and a file iterator, this auto-completer is able to auto-complete paths.
  If the root is undefined, it will be set to the current working directory. At
  each auto-completion, a new instance of the file iterator is created by a
  factory. This latter receives the path to iterate as a unique argument. By
  default, the factory is defined by the <code>getDefaultIteratorFactory</code>
  static method on <code>Hoa\Console\Readline\Autocompleter\Path</code>. The
  factory builds a file iterator of type
  <a href="http://php.net/directoryiterator"><code>DirectoryIterator</code></a>.
  Each value computed by the iterator must be an object of type
  <a href="http://php.net/splfileinfo"><code>SplFileInfo</code></a>. Thus, to
  auto-complete all the files and directories from the
  <a href="@central_resource:path=Library/Console"><code>hoa://Library/Console</code></a>
  root, we will write:</p>
  <pre><code class="language-php">$rl->setAutocompleter(
    new Hoa\Console\Readline\Autocompleter\Path(
        resolve('hoa://Library/Console')
    )
);</code></pre>
  <p>Using a factory offers a lot of <strong>flexibility</strong> and allows us
  to use any file iterator, such as <code>Hoa\File\Finder</code> (please, see
  <a href="@hack:chapter=File">the <code>Hoa\File</code> library</a>). Thus, to
  only auto-complete not hidden files and directories that have been modified
  the last 6 months and sorted by their size, we will write:</p>
  <pre><code class="language-php">$rl->setAutocompleter(
    new Hoa\Console\Readline\Autocompleter\Path(
        resolve('hoa://Library/Console'),
        function ($path) {
            $finder = new Hoa\File\Finder();
            $finder->in($path)
                   ->files()
                   ->directories()
                   ->maxDepth(1)
                   ->name('#^(?!\.).#')
                   ->modified('since 6 months')
                   ->sortBySize();

            return $finder;
        }
    )
);</code></pre>
  <p>We can replace the local file iterator by another totally
  <strong>different</strong> iterator: on files that are stored in another
  machine, a third party service or even resources that are not files but have
  path-like URI.</p>
  <p>Finally, we can aggregate several auto-completers together thanks to the
  <code>Hoa\Console\Readline\Autocompleter\Aggregate</code> class. The
  declaration order of auto-completers is important: the first one that matches
  a word to auto-complete will break the loop over all the auto-completers.
  Thus, to auto-complete paths and words, we will write:</p>
  <pre><code class="language-php">$rl->setAutocompleter(
    new Hoa\Console\Readline\Autocompleter\Aggregate([
        new Hoa\Console\Readline\Autocompleter\Path(),
        new Hoa\Console\Readline\Autocompleter\Word($words)
    ])
);
</code></pre>
  <p>The <code>getAutocompleters</code> method from
  <code>Hoa\Console\Readline\Autocompleter\Aggregate</code> returns an
  <a href="http://php.net/arrayobject"><code>ArrayObject</code></a> object for
  more flexibility. We can consequently add or delete auto-completers after
  having declared them in the constructor.</p>
  <figure>
    <img src="https://central.hoa-project.net/Resource/Library/Console/Documentation/Image/Readline_autocompleters.gif?format=raw" />
    <figcaption>Example of an aggregation of the
    <code>Hoa\Console\Readline\Autocompleter\Path</code> auto-completer with
    <code>Hoa\Console\Readline\Autocompleter\Word</code>.</figcaption>
  </figure>

  <h2 id="Reading_options" for="main-toc">Reading options</h2>

  <p>A big benefit of programs with a command line interface is their
  <strong>flexibility</strong>. They are <strong>dedicated</strong> to one
  (little) <strong>task</strong> and we are able to parameterize them thanks to
  <strong>options</strong> that they exposed. The <strong>reading</strong> of
  those options must be very simple and straightforward because this is a
  repetitive and subtle task. The <code>Hoa\Console\Parser</code> and
  <code>Hoa\Console\GetOption</code> classes act as a <strong>duo</strong> to
  solve this problem.</p>

  <h3 id="Analyzing_options" for="main-toc">Analyzing options</h3>

  <p>We start with <code>Hoa\Console\Parser</code> that
  <strong>analyzes</strong> options given to a program. Whatever the options we
  would like to have, we just analyze them for now. Let's start by using the
  <code>parse</code> method:</p>
  <pre><code class="language-php">$parser = new Hoa\Console\Parser();
$parser->parse('-s --long=value input');

print_r($parser->getSwitches());
print_r($parser->getInputs());

/**
 * Will output:
 *     Array
 *     (
 *         [s] => 1
 *         [long] => value
 *     )
 *     Array
 *     (
 *         [0] => input
 *     )
 */</code></pre>
  <p>Let's see of what a command line is composed. We have two categories: the
  <strong>options</strong> (switches) and the <strong>inputs</strong>. The
  inputs are everything that is not an option. An option can have two forms:
  <strong>short</strong> if it has only one character or <strong>long</strong>
  if it has many.</p>
  <p>Thus, <code>-s</code> is a short option and <code>--long</code> is a
  long option. However, we have to consider the number of hyphen in front of the
  option: with two hyphens, it will always be a long option, with one hyphen, it
  depends. There is two schools that differenciate themselves with one
  <strong>parameter</strong>: <em>long only</em>. Let's take an example:
  <code>-abc</code> is considered as <code>-a -b -c</code> if the <em>long
  only</em> parameter is set to <code>false</code>, else it will be equivalent
  to a long option, such as <code>--abc</code>. Most of the time, this parameter
  is set to <code>false</code> by default and <code>Hoa\Console\Parser</code>
  has adopted the position of the majority. To modify this parameter, we have to
  use the <code>setLongOnly</code> method, let's see though:</p>
  <pre><code class="language-php">// long only is set to false.
$parser->parse('-abc');
print_r($parser->getSwitches());

$parser->setLongOnly(true);

// long only is set to true.
$parser->parse('-abc');
print_r($parser->getSwitches());

/**
 * Will output:
 *     Array
 *     (
 *         [a] => 1
 *         [b] => 1
 *         [c] => 1
 *     )
 *     Array
 *     (
 *         [abc] => 1
 *     )
 */</code></pre>
  <p>An option can be of two kinds: <strong>boolean</strong> or
  <strong>valued</strong>. If no value is associated, it is considered as a
  boolean. Thus, <code>-s</code> represents <code>true</code>, but <code>-s
  -s</code> represents <code>false</code>, <code>-s -s -s</code> represents
  <code>true</code> and so on. A boolean option behaves like a
  <strong>switch</strong>. A valued option has an associated value by using
  either a space or an equal sign (symbol <code>=</code>). Here is a
  non-exhaustive list of potential syntaxes (we use a short option but it could
  be a long one):</p>
  <ul>
    <li><code>-x=value</code>: <code>value</code>,</li>
    <li><code>-x=va\ lue</code>: <code>va lue</code>,</li>
    <li><code>-x="va lue"</code>: <code>va lue</code>,</li>
    <li><code>-x="va l\"ue"</code>: <code>va l"ue</code>,</li>
    <li><code>-x value</code>: <code>value</code>,</li>
    <li><code>-x va\ lue</code>: <code>va lue</code>,</li>
    <li><code>-x "value"</code>: <code>value</code>,</li>
    <li><code>-x "va lue"</code>: <code>va lue</code>,</li>
    <li><code>-x va\ l"ue</code>: <code>va l"ue</code>,</li>
    <li><code>-x 'va "l"ue'</code>: <code>va "l"ue</code>,</li>
    <li>etc.</li>
  </ul>
  <p>The simple (symbol <code>'</code>) and double (symbol <code>"</code>)
  quotes are supported. But be aware that there is particular syntaxes which are
  still not <strong>standards</strong>:</p>
  <ul>
    <li><code>-x=-value</code>: <code>-value</code>,</li>
    <li><code>-x "-value"</code>: <code>-value</code>,</li>
    <li><code>-x \-value</code>: <code>-value</code>,</li>
    <li><code>-x -value</code>: is the equivalent of two booleans,
    <code>-x</code> and <code>-value,</code></li>
    <li><code>-x=-7</code>: <code>-7</code>,</li>
    <li>etc.</li>
  </ul>
  <p><em>A l'instar</em> of boolean options that behave like switches, the
  valued options <strong>rewrite</strong> their values if they are declared more
  than once. Thus, <code>-a=b -a=c</code> represents <code>c</code>.</p>
  <p>Finally, there is values that are considered as <strong>special</strong>.
  We distinguish two of them:</p>
  <ul>
    <li><strong>lists</strong>, with the help of a comma as a separator:
    <code>-x=a,b,c</code>,</li>
    <li><strong>intervalles</strong>, with the help of the <code>:</code> symbol
    (without spaces around it): <code>-x=1:7</code>.</li>
  </ul>
  <p>Without any specific manipulation, those values will not be considered as
  special. We will have to use the
  <code>Hoa\Console\Parser::parseSpecialValue</code> method as we will see
  bellow.</p>

  <h3 id="Read_options_and_inputs" for="main-toc">Read options and inputs</h3>

  <p>We know how to analyze options but this is not enough to read them
  correctly. We have to define a little <strong>semantics</strong>: what do
  their expect, what is their nature etc. We will use the
  <code>Hoa\Console\GetOption</code> class. An option is defined by:</p>
  <ul>
    <li>a <strong>long</strong> name,</li>
    <li>a <strong>short</strong> name,</li>
    <li>a <strong>type</strong>, given by one of the
    <code>Hoa\Console\GetOption</code> constants among:
      <ul>
        <li><code>NO_ARGUMENT</code> if the option is a boolean one,</li>
        <li><code>REQUIRED_ARGUMENT</code> if the option is a valued one,</li>
        <li><code>OPTIONAL_ARGUMENT</code> if the option can receive a
        value.</li>
      </ul>
    </li>
  </ul>
  <p>These three informations <strong>must</strong> be specified. They must be
  given to the constructor of <code>Hoa\Console\GetOption</code> as first
  argument. The second one is the option analyzer (the analysis must be
  <strong>already</strong> done). Thus, we describe two options:
  <code>extract</code> that is a boolean option and <code>directory</code> that
  is a valued option:</p>
  <pre><code class="language-php">$parser = new Hoa\Console\Parser();
$parser->parse('-x --directory=value inputA inputB inputC');

$options = new Hoa\Console\GetOption(
    [
        // long name                  type                  short name
        //   ↓                         ↓                         ↓
        ['extract',   Hoa\Console\GetOption::NO_ARGUMENT,       'x'],
        ['directory', Hoa\Console\GetOption::REQUIRED_ARGUMENT, 'd']
    ],
    $parser
);</code></pre>
  <p>We are now ready to read our options! The options reader behaves like an
  iterator, or like a <strong>pipette</strong> though, thanks to the
  <code>getOption</code> method. This method returns the short name of the
  option currently read and will assign the value of the option (a boolean or a
  string) to its first argument passed by reference. When the pipette is empty,
  the <code>getOption</code> method will return <code>false</code>. This
  structure might seem original but it is widely <strong>spread</strong>, you
  will not be lost when seeing it in other progams (examples
  <a href="http://kernel.org/doc/man-pages/online/pages/man3/getopt.3.html#EXAMPLE"
     title="getopt(3), Linux Programmer's Manual">in Linux</a>,
  <a href="http://freebsd.org/cgi/man.cgi?query=getopt&amp;sektion=3#EXAMPLES"
     title="getopt(3), FreeBSD Library Functions Manual">in FreeBSD</a> or
  <a href="http://developer.apple.com/library/Mac/#documentation/Darwin/Reference/ManPages/man3/getopt.3.html"
     title="getopt(3), BSD Library Functions Manual">in Mac OS X</a> —same code
     base—). The simplest way to read options are to define them default values
     and then to use <code>getOption</code>, thus:</p>
  <pre><code class="language-php">$extract   = false;
$directory = '.';

//          short name                  value
//               ↓                        ↓
while (false !== $c = $options->getOption($v)) {
    switch($c) {
        case 'x':
            $extract = $v;

            break;

        case 'd':
            $directory = $v;

            break;
    }
}

var_dump($extract, $directory);

/**
 * Will output:
 *     bool(true)
 *     string(5) "value"
 */</code></pre>
  <p>We read it like this: “while we have an option to read, we get the short
  name in <code>$c</code> and its value in <code>$v</code>, then we see what to
  do”.</p>
  <p>To read inputs, we will use the <code>Hoa\Console\Parser::listInputs</code>
  whose all arguments (a total of 26) are passed by <strong>reference</strong>.
  Thus:</p>
  <pre><code class="language-php">$parser->listInputs($inputA, $inputB, $inputC);

var_dump($inputA, $inputB, $inputC);

/**
 * Will output:
 *     string(6) "inputA"
 *     string(6) "inputB"
 *     string(6) "inputC"
 */</code></pre>
  <p>Attention, this approach implies that the inputs are
  <strong>ordered</strong> (as usualy most of the time). But also, reading the
  inputs without having formely given the analyzer to
  <code>Hoa\Console\GetOption</code> can lead to unexpected results (because by
  default, all options are considered as booleans). If we would like all the
  inputs and analyze them manually if they are not ordered, we can use the
  <code>Hoa\Console\Parser::getInputs</code> method which will return all the
  inputs.</p>

  <h3 id="Special_or_ambiguous_options" for="main-toc">Special or ambiguous
  options</h3>

  <p>Back to our <code>Hoa\Console\Parser::parseSpecialValue</code> method. It
  takes two arguments: a value and an array of keywords. We re-use our example
  and modify the case of the <code>d</code> option:</p>
  <pre data-line="8-11"><code class="language-php">while (false !== $c = $options->getOption($v)) {
    switch($c) {
        case 'x':
            $extract = $v;

            break;

        case 'd':
            $directory = $parser->parseSpecialValue($v, ['HOME' => '/tmp']);

            break;
    }
}

print_r($directory);</code></pre>
  <p>If we try with <code>-d=a,b,HOME,c,d</code> then <code>-d</code> will have
  the following value:</p>
  <pre><code class="language-php">/**
 * Array
 * (
 *     [0] => a
 *     [1] => b
 *     [2] => /tmp
 *     [3] => c
 *     [4] => d
 * )
 */</code></pre>
  <p>Finally, when a read option does not exist but it is
  <strong>close</strong> to an existing option modulo some
  <strong>typos</strong> (for example <code>--dirzctory</code> instead of
  <code>--directory</code>), we can use the <code>__ambiguous</code> case to
  capture and compute it:</p>
  <pre data-line="13-16"><code class="language-php">while (false !== $c = $options->getOption($v)) {
    switch($c) {
        case 'x':
            $extract = $v;

            break;

        case 'd':
            $directory = $parser->parseSpecialValue($v, ['HOME' => '/tmp']);

            break;

        case '__ambiguous':
            print_r($v);

            break;
    }
}</code></pre>
  <p>The value (in <code>$v</code>) is an array with three entries. For example
  with <code>--dirzctory</code>, we have:</p>
  <pre><code class="language-php">/**
 * Array
 * (
 *     [solutions] => Array
 *         (
 *             [0] => directory
 *         )
 *
 *     [value] => y
 *     [option] => dirzctory
 * )
 */</code></pre>
  <p>The <code>solutions</code> key provides all the <strong>similar</strong>
  options, the <code>value</code> key gives the value of the option and
  <code>option</code> is the <strong>original</strong> read name. It is part to
  the user to decide what to do based on these informations. We can use the
  <code>Hoa\Console\GetOption::resolveOptionAmbiguity</code> method by giving it
  the array, and it will choose the best option if it exists:</p>
  <pre><code class="language-php">    case '__ambiguous':
        $options->resolveOptionAmbiguity($v);

        break;
</code></pre>
  <p>It is preferable to <strong>advise</strong> the user that an ambiguity
  happened and ask her a decision. Sometimes, it can be
  <strong>dangerous</strong> to make decision in her place.</p>

  <h3 id="Integrate_a_router_and_a_dispatcher" for="main-toc">Integrate a router
  and a dispatcher</h3>

  <p>So far, we coerced the options and the inputs to the analyzer.
  <code>Hoa\Router\Cli</code> allows to <strong>extract</strong> data from a
  command line program. One method interests us:
  <code>Hoa\Router\Cli::getURI</code> will give us all the options and inputs of
  the running program, that we will <strong>provide</strong> to our analyzer.
  Thus:</p>
  <pre data-line="2"><code class="language-php">$parser = new Hoa\Console\Parser();
$parser->parse(Hoa\Router\Cli::getURI());

// …</code></pre>
  <p>Now, it is possible to interprete the options that we will give to our
  program. If you have written the tests in a file named <code>Test.php</code>,
  then you will be able to write:</p>
  <pre><code class="language-shell">$ php Test.php -x -d=a,b,HOME,c,d inputA inputB
bool(true)
Array
(
    [0] => a
    [1] => b
    [2] => /tmp
    [3] => c
    [4] => d
)
string(6) "inputA"
string(6) "inputB"
NULL</code></pre>
  <p>The <code>-x</code> option is set to <code>true</code>, the <code>-d</code>
  option is an array (because we have analyzed it with the
  <code>Hoa\Console\Parser::parseSpecialValue</code> method), and we have
  <code>inputA</code>, <code>inputB</code> and <code>null</code> as inputs.</p>
  <p>This is a good start and we can stop here most of the time. But it is
  possible to go further by using a <strong>dispatcher</strong>: writing
  commands in several functions or classes and call them regarding the given
  options and inputs to our program. We recommend to read the source code of
  <a href="@central_resource:path=Library/Cli/Bin/Hoa.php"><code>hoa://Library/Cli/Bin/Hoa.php</code></a>
  to help yourself, along with the
  <a href="@hack:chapter=Router"><code>Hoa\Router</code></a> and
  <a href="@hack:chapter=Dispatcher"><code>Hoa\Dispatcher</code></a> chapters.
  We propose a quick example without giving too much details about those
  libraries.</p>
  <p>The idea is as follows. Thanks to <code>Hoa\Router\Cli</code> we are going
  to extract data of the following form: <code>$ php script.php
  <em>controller</em> <em>tail</em></code>, where
  <code><em>controller</em></code> will be the name of the controller (of a
  class) on which we will call the <code>main</code> action (it means the
  <code>main</code> method with its default parameters) and where
  <code><em>tail</em></code> represents the options and the inputs. The name of
  the controller is identified by the special <code>_call</code> variable (from
  <code>Hoa\Router\Cli</code>) and the options along with the inputs are
  identified by <code>_tail</code> (from <code>Hoa\Dispatcher\Kit</code>). The
  options and the inputs are not mandatory. Then, we will use
  <code>Hoa\Dispatcher\Basic</code> with the dedicated kit of terminals, namely
  <code>Hoa\Console\Dispatcher\Kit</code>.  The dispatcher will try to load the
  <code>Application\Controller\<em>controller</em></code> class by default, and
  the autoloader will load them from the
  <code>hoa://Application/Controller/<em>controller</em></code> directory. We
  will then set quickly where the application is located. Finally, the exit code
  of our program will be given by the value returned by our controller and
  action. If an error occurred, we will print it and force an exit code greater
  than zero. Thus:</p>
  <pre><code class="language-php">try {
    // Prepare the router.
    $router = new Hoa\Router\Cli();
    $router->get(
        'g',
        '(?&amp;lt;_call>\w+)(?:\s+(?&amp;lt;_tail>.+))?'
    );

    // Prepare the dispatcher.
    $dispatcher = new Hoa\Dispatcher\ClassMethod([
        'synchronous.call' => 'Application\Controller\(:call:U:)',
        'synchronous.able' => 'main'
    ]);
    $dispatcher->setKitName('Hoa\Console\Dispatcher\Kit');

    // Dispatch!
    exit($dispatcher->dispatch($router));
} catch (Hoa\Exception $e) {
    echo $e->raise(true);
    exit($e->getCode() + 1);
}</code></pre>
  <p>At the same level of our program, let's create the
  <code>Application/Controller/</code> directory with the <code>Foo.php</code>
  file inside, which will contain the following code:</p>
  <pre><code class="language-php">&amp;lt;?php

namespace Application\Controller;

class Foo extends \Hoa\Console\Dispatcher\Kit
{
    protected $options = [
        ['extract',   \Hoa\Console\GetOption::NO_ARGUMENT,       'x'],
        ['directory', \Hoa\Console\GetOption::REQUIRED_ARGUMENT, 'd'],
        ['help',      \Hoa\Console\GetOption::NO_ARGUMENT,       'h']
    ];

    public function MainAction()
    {
        $extract   = false;
        $directory = '.';

        while (false !== $c = $this->getOption($v)) {
            switch($c) {
              case 'x':
                  $extract = $v;

                  break;

              case 'd':
                  $directory = $this->parser->parseSpecialValue($v, ['HOME' => '/tmp']);

                  break;

              case 'h':
                  return $this->usage();
            }
        }

        echo 'extract:   ';
        var_dump($extract);
        echo 'directory: ';
        print_r($directory);

        return;
    }

    public function usage()
    {
        echo
            'Usage   : foo &amp;lt;options>', "\n",
            'Options :', "\n",
            $this->makeUsageOptionsList([
                'x' => 'Whether we need to extract.',
                'd' => 'Directory to extract.',
                'h' => 'This help.'
            ]);
    }
}</code></pre>
  <p>Our class extends our kit to benefit from the provided methods. Among other
  things, its own <code>getOption</code> method that will exploit the
  <code>$options</code> attribute where the options are declared,
  <code>makeUsageOptionsList</code> to print a usage, its own
  <code>resolveOptionAmbiguity</code> method that asks a confirmation from the
  user, the router access through the <code>$router</code> attribute etc. Kits
  offer <strong>services</strong> to the application, they
  <strong>aggregate</strong> services offered by the libraries. Now, let's
  test:</p>
  <pre><code class="language-shell">$ php Test.php foo -x -d=1:3
extract:   bool(true)
directory: Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)</code></pre>
  <p>Awesome!</p>
  <p>Let's note that the <code>hoa</code> script is exactly build like this. Do
  not hesitate to find inspiration from it.</p>

  <h2 id="Processus" for="main-toc">Processus</h2>

  <p>In our context, a <strong>processus</strong> is a classical program that
  is executed in a <strong>terminal</strong>. The interesting part is that such
  a program <strong>communicates</strong> with the rest of its
  <strong>environment</strong> thanks to <strong>pipes</strong>, numbered from
  zero. Some of them have even names:</p>
  <ul>
    <li><code>STDIN</code> (<code>0</code>) to read <strong>inputs</strong>
    (<em>standard input</em>),</li>
    <li><code>STDOUT</code> (<code>1</code>) to write <strong>outputs</strong>
    (<em>standard output</em>),</li>
    <li><code>STDERR</code> (<code>2</code>) to write <strong>errors</strong>
    (<em>standard error</em>).</li>
  </ul>
  <p>When a processus is executed in a terminal, <code>STDIN</code> will use the
  <strong>keyboard</strong> as the source of data, and <code>STDOUT</code> with
  <code>STDERR</code> are linked to the <strong>window</strong> of the terminal.
  But when a processus is executed in a <strong>sub-terminal</strong>, it means
  executed from another processus, <code>STDIN</code> is no longer linked to the
  keyboard, like <code>STDOUT</code> and <code>STDERR</code> are not linked to
  the screen. This is the parent processus that will read and write on these
  streams to <strong>interact</strong> with the “sub”-processus. This mechanism
  is called a <strong>redirection</strong> of stream, we use it very often when
  we write a command line (please, see the
  <a href="http://gnu.org/software/bash/manual/bashref.html#Redirections">section
  Redirections from the Bash Reference Manual</a>). What we are going to do use
  another syntax but the mechanism is exactly the same.</p>
  <p>It is very important to know that these streams are all
  <strong>asynchronous</strong> from each other. Not one of these streams will
  have an impact on another one, there is no link between them and that is very
  important for the rest of this section.</p>
  <p>From the PHP level, it is possible to access to these streams by using
  respectively the following URI: <code>php://stdin</code>,
  <code>php://stdout</code> and <code>php://stderr</code>. However, we also have
  the eponymous <code>STDIN</code>, <code>STDOUT</code> and <code>STDERR</code>
  constants. They are defined as follows (example with <code>STDIN</code>):</p>
  <pre><code class="language-php">define('STDIN', fopen('php://stdin', 'r'));</code></pre>
  <p>These streams are available if and only if the program is executed from a
  command line. Remind that pipes are identified by numbers. We are then able to
  use <code>php://fd/0</code> to represent <code>STDIN</code>,
  <code>php://fd/1</code> to represent <code>STDOUT</code> etc. The
  <code>php://fd/<em>i</em></code> URI allows to access the file with the
  <code><em>i</em></code> <strong>descriptor</strong>.</p>

  <h3 id="Very_basic_execution" for="main-toc">Very basic execution</h3>

  <p>The <code>Hoa\Console\Processus</code> class provides a very
  <strong>quick</strong> way to execute a processus and get the result of
  <code>STDOUT</code>. This is the most common case. Thus, we will use the
  <code>execute</code> static method:</p>
  <pre><code class="language-php">var_dump(Hoa\Console\Processus::execute('id -u -n'));

/**
 * Could output:
 *     string(3) "hoa"
 */</code></pre>
  <p>By default, the command will be escaped for security reasons. If you are
  confident in the command, you can desactivate the escaping by setting the
  second argument to <code>false</code>.</p>
  <p>We have no control on the pipes and even if it is suitable for the majority
  of cases, this is not enough when we would like a minimum of interaction with
  the processus.</p>

  <h3 id="Reading_and_writing" for="main-toc">Reading and writing</h3>

  <p>Let's see how to <strong>interact</strong> with a processus. We will
  consider the following <code>LittleProcessus.php</code> program:</p>
  <pre><code class="language-php">&amp;lt;?php

$range = range('a', 'z');

while (false !== $line = fgets(STDIN)) {
    echo '> ', $range[intval($line)], "\n";
}</code></pre>
  <p>To test and understand its behavior, let's write the following command line
  and hit <code>3</code> and <code>4</code> on the keyboard:</p>
  <pre><code class="language-shell">$ php LittleProcessus.php
3
> d
4
> e
</code></pre>
  <p>We can also write:</p>
  <pre><code class="language-shell">$ seq 0 4 | php LittleProcessus.php
> a
> b
> c
> d
> e</code></pre>
  <p>Our program will read each line on the standard input, considering it is a
  number and transforming it into a character that will be printed on the
  standard output. We would like to execute this program by giving it our own
  custom list of numbers (like the <code>seq</code> program does) and observe
  the produced result.</p>
  <p>An instance of the <code>Hoa\Console\Processus</code> class represents a
  <strong>processus</strong>. During the instanciation, we can set:</p>
  <ul>
    <li>the <strong>name</strong> of the processus,</li>
    <li>its <strong>options</strong>,</li>
    <li>the <strong>description</strong> of pipes.</li>
  </ul>
  <p>There is other arguments but we will see them further.</p>
  <p>The description of pipes has the form of an array where each key represents
  the number of the pipe (more generally, this is the <code><em>i</em></code>
  from <code>php://fd/<em>i</em></code>) and its value is also an array
  describing the nature of the pipe: either a “real” pipe, or a file with their
  reading or writing mode (among <code>r</code>, <code>w</code> or
  <code>a</code>). Let's illustrate with an example:</p>
  <pre><code class="language-php">$processus = new Hoa\Console\Processus(
    'php',
    ['LittleProcessus.php'],
    [
        // STDIN.
        0 => ['pipe', 'r'],
        // STDOUT.
        1 => ['file', '/tmp/output', 'a']
    ]
);</code></pre>
  <p>In this case, <code>STDIN</code> is a pipe and <code>STDOUT</code> is the
  <code>/tmp/output</code> file. If we do not set a descriptor, it will be
  equivalent to write:</p>
  <pre><code class="language-php">$processus = new Hoa\Console\Processus(
    'php',
    ['LittleProcessus.php'],
    [
        // STDIN.
        0 => ['pipe', 'r'],
        // STDOUT.
        1 => ['pipe', 'w'],
        // STDERR.
        2 => ['pipe', 'w']
    ]
);</code></pre>
  <p>Each pipe is identified as a stream and can be manipulated as such. When a
  pipe is in <strong>reading</strong> (with the <code>r</code> mode), it means
  that the processus will <strong>read</strong> from it. So we, the parent
  processus, will <strong>write</strong> on this pipe. Let's take the example of
  <code>STDIN</code>: the processus reads from <code>STDIN</code> what the
  keyboard has written on it. And conversely, when a pipe is in
  <strong>writing</strong> (with the <code>w</code> mode), it means that we will
  <strong>read</strong> from it. Let's take the example of <code>STDOUT</code>:
  the screen will read what the processus has written to it.</p>
  <p>The <code>Hoa\Console\Processus</code> class extends the
  <a href="@hack:chapter=Stream"><code>Hoa\Stream</code></a> class, and
  consequently, we have all the necessary tools to read and write on the pipe of
  our choice. This class also provides several <strong>listeners</strong>:</p>
  <ul>
    <li><code>start</code>, when the processus is started,</li>
    <li><code>stop</code>, when the processus is stopped,</li>
    <li><code>input</code>, when the reading streams are ready,</li>
    <li><code>output</code>, when the writing streams are ready,</li>
    <li><code>timeout</code>, when the processus is executing too much
    time.</li>
  </ul>
  <p>Let's take directly an example. We will execute the <code>php
  LittleProcessus.php</code> processus and attach functions to the following
  listeners: <code>input</code> to write a sequence of numbers and
  <code>output</code> to read the result.</p>
  <pre><code class="language-php">$processus = new Hoa\Console\Processus('php LittleProcessus.php');
$processus->on('input', function ($bucket) {
    $source = $bucket->getSource();
    $data   = $bucket->getData();

    echo 'INPUT (', $data['pipe'], ')', "\n";

    $source->writeAll(
        implode("\n", range($i = mt_rand(0, 21), $i + 4)) . "\n"
    );

    return false;
});
$processus->on('output', function ($bucket) {
    $data = $bucket->getData();

    echo 'OUTPUT (', $data['pipe'], ') ', $data['line'], "\n";

    return;
});
$processus->run();

/**
 * Could output:
 *     INPUT (0)
 *     OUTPUT (1) > s
 *     OUTPUT (1) > t
 *     OUTPUT (1) > u
 *     OUTPUT (1) > v
 *     OUTPUT (1) > w
 */</code></pre>
  <p>Now, let's see the details to understand well.</p>
  <p>When a <strong>reading</strong> stream is <strong>ready</strong>, the
  <code>input</code> listener will be fired. Only one data is sent:
  <code>pipe</code>, that contains the number of the pipe (the
  <code><em>i</em></code> of <code>php://fd/<em>i</em></code>). When a
  <strong>writing</strong> stream is ready, the <code>output</code> listener is
  fired. Two data are sent: <code>pipe</code> (like <code>input</code>) and
  <code>line</code> that contains the <strong>received line</strong>.</p>
  <p>We see in the function attached to the <code>input</code> listener that we
  write a sequence of numbers concatenated by <code>\n</code> (one number per
  line). In order to achieve this, we use the <code>writeAll</code> method. By
  default, the writing methods write on the <code>0</code> pipe. To change this
  behavior, we will have to set the number of the pipe as the second argument of
  the writing methods. Same for the reading methods but the default pipe is
  <code>1</code>.</p>
  <p>When the callable attached to a listener returns <code>false</code>, the
  pipe that has fired this call will be <strong>closed</strong> just after. In
  our case, the function attached to <code>input</code> returns
  <code>false</code> just after having written the data, we no longer need this
  pipe. It is important for <strong>performance</strong> reasons to close pipes
  as soon as possible.</p>
  <p>Finally, to <strong>execute</strong> the processus, we use the
  <code>Hoa\Console\Processus::run</code> method with a null arity.</p>
  <p>In our example, we write all data at once but we can send them as soon as
  they are ready, which is more efficient because the processus does no wait a
  big bucket of data and can compute them gradually. Let's modify our example to
  write a data each time <code>STDIN</code> is ready:</p>
  <pre><code class="language-php">$processus->on('input', function ($bucket) {
    static $i = null;
    static $j = 5;

    if (null === $i) {
        $i = mt_rand(0, 20);
    }

    $data = $bucket->getData();

    echo 'INPUT (', $data['pipe'],')', "\n";

    $source = $bucket->getSource();
    $source->writeLine($i++);
    usleep(50000);

    if (0 >= $j--) {
        return false;
    }

    return;
});</code></pre>
  <p>We initialize two variables: <code class="language-php">$i</code> and
  <code class="language-php">$j</code>, that hold the number to send and the
  maximum number of data to send. We introduce a voluntary latency with
  <code class="language-php">usleep(50000)</code> in order that
  <code>STDOUT</code> to be ready, only to illustrate our example. In this case,
  the output would be:</p>
  <pre><code class="language-php">/** Could output:
 *     INPUT (0)
 *     OUTPUT (1) > h
 *     INPUT (0)
 *     OUTPUT (1) > i
 *     INPUT (0)
 *     OUTPUT (1) > j
 *     INPUT (0)
 *     OUTPUT (1) > k
 *     INPUT (0)
 *     OUTPUT (1) > l
 *     INPUT (0)
 *     OUTPUT (1) > m
 */</code></pre>
  <p>The processus is waiting an input and read data when they are received.
  Once we have sent all the data, we close the pipe.</p>
  <p>The processus will close itself. We have the
  <code>Hoa\Console\Processus::getExitCode</code> method to know the exit
  <strong>code</strong> of the processus. Attention, a <code>0</code> code
  represents a success. Because it is a common error, there is the
  <code>Hoa\Console\Processus::isSuccessful</code> method to know if the
  processus has been executed with success or not.</p>

  <h3 id="Detect_the_type_of_pipes" for="main-toc">Detect the type of pipes</h3>

  <p>Sometimes, it is useful to know the <strong>type</strong> of pipes, it
  means if it is a <strong>direct</strong> (regular) use, a
  <strong>pipe</strong> or a <strong>redirection</strong>. We will make use of
  the <code>Hoa\Console\Console</code> class and its <code>isDirect</code>,
  <code>isPipe</code> and <code>isRedirection</code> static methods to get these
  informations.</p>
  <p>Let's take an example to understand. Let's write the <code>Type.php</code>
  file that will study the type of <code>STDOUT</code>:</p>
  <pre><code class="language-php">echo 'is direct:      ';
var_dump(Hoa\Console\Console::isDirect(STDOUT));

echo 'is pipe:        ';
var_dump(Hoa\Console\Console::isPipe(STDOUT));

echo 'is redirection: ';
var_dump(Hoa\Console\Console::isRedirection(STDOUT));</code></pre>
  <p>And now, let's execute this file to see the result:</p>
  <pre><code class="language-shell">$ php Type.php
is direct:      bool(true)
is pipe:        bool(false)
is redirection: bool(false)

$ php Type.php | xargs -I@ echo @
is direct:      bool(false)
is pipe:        bool(true)
is redirection: bool(false)

$ php Type.php > /tmp/foo; cat /tmp/foo
is direct:      bool(false)
is pipe:        bool(false)
is redirection: bool(true)</code></pre>
  <p>In the first case, <code>STDOUT</code> is <strong>direct</strong> (for
  <code>STDOUT</code>, it means that it is <strong>linked</strong> to the
  screen, for <code>STDIN</code>, it will be linked to the keyboard etc.). In
  the second case, <code>STDOUT</code> is a <strong>pipe</strong>, it means that
  it is <strong>attached</strong> to the <code>STDIN</code> of the command
  written after the <code>|</code> symbol. In the last case, <code>STDOUT</code>
  is a <strong>redirection</strong>, it means that it is
  <strong>redirected</strong> in the <code>/tmp/foo</code> file (that we print
  just after). The operation can be done on <code>STDIN</code>,
  <code>STDERR</code> or any other resource.</p>
  <p>Knowing the type of pipes can allow different behaviors according to the
  <strong>context</strong>. For example,
  <code>Hoa\Console\Readline\Readline</code> reads on <code>STDIN</code>. If its
  type is a pipe or a redirection, the advanced edition mode of the line will be
  disabled and it will return <code>false</code> when there will be no more
  things to read. Another example, the commands verbosity of the
  <code>hoa</code> script uses the type of <code>STDOUT</code> as the default
  value: direct to be verbose, else not verbose. Try the following examples to
  see the difference:</p>
  <pre><code class="language-shell">$ hoa --no-verbose
$ hoa | xargs -I@ echo @</code></pre>
  <p>Examples are numerous but be careful to use this feature with precautions.
  We have to adapt the behaviors but keep them <strong>consistent</strong>.</p>

  <h3 id="Execution_conditions" for="main-toc">Execution conditions</h3>

  <p>The processus is executed in a particular <strong>directory</strong> and a
  particular <strong>environment</strong>. This directory is called the current
  working directory, often abbreviated <abbr lang="en">cwd</abbr>. It defines
  the directory where the processus will be executed. We can find it in PHP with
  <a href="http://php.net/getcwd">the <code>getcwd</code> function</a>. The
  environment is defined by an array, which can be retrieved for example by
  executing <code>/usr/bin/env</code>. For example, the <code>PATH</code> is
  defined in this environment. These data are given as fourth and fifth
  arguments of the <code>Hoa\Console\Processus</code> constructor. Thus:</p>
  <pre><code class="language-php">$processus = new Hoa\Console\Processus(
    'php',
    null, /* no option         */
    null, /* use default pipes */
    '/tmp',
    [
        'FOO'  => 'bar',
        'BAZ'  => 'qux',
        'PATH' => '/usr/bin:/bin'
    ]
);
$processus->on('input', function (Hoa\Event\Bucket $bucket) {
    $bucket->getSource()->writeAll(
        '&amp;lt;?php' . "\n" .
        'var_dump(getcwd());' . "\n" .
        'print_r($_ENV);'
    );

    return false;
});
$processus->on('output', function (Hoa\Event\Bucket $bucket) {
    $data = $bucket->getData();
    echo '> ', $data['line'], "\n";

    return;
});
$processus->run();

/**
 * Will output:
 *     > string(12) "/tmp"
 *     > Array
 *     > (
 *     >     [FOO] => bar
 *     >     [PATH] => /usr/bin:/bin
 *     >     [PWD] => /tmp
 *     >     [BAZ] => qux
 *     >     [_] => /usr/bin/php
 *     >
 *     > )
 */</code></pre>
  <p>If the current working directory is not defined, we will use the one of the
  program. If the environment is not defined, the processus will use the one of
  its parent.</p>
  <p>We are also able to set a <strong>maximum time</strong> in seconds in order
  to get a <strong>response</strong> from the processus (defined to 30 seconds
  by default). This is the last argument of the constructor. We can use the
  <code>Hoa\Console\Processus::setTimeout</code> method. To know when this time
  is reached, we must use the <code>timeout</code> listener. No action will be
  done automatically. We can for example terminate the processus thanks to the
  <code>Hoa\Console\Processus::terminate</code> method. Thus:</p>
  <pre><code class="language-php">$processus = new Hoa\Console\Processus('php');

// 3 seconds is enough…
$processus->setTimeout(3);

// Sleep 10 seconds.
$processus->on('input', function (Hoa\Event\Bucket $bucket) {
    $bucket->getSource()->writeAll('&amp;lt;?php sleep(10);');

    return false;
});

// Terminate the processus on timeout.
$processus->on('timeout', function (Hoa\Event\Bucket $bucket) {
    echo 'TIMEOUT, terminate', "\n";
    $bucket->getSource()->terminate();

    return;
});

$processus->run();

/**
 * Will output (after 3 secondes):
 *     TIMEOUT, terminate
 */</code></pre>
  <p>No action is done automatically because they can be numerous. Maybe we can
  unblock the processus, or close it to open other ones, emit some logs etc.</p>
  <p>About the <code>terminate</code> method, it can take several different
  values, defined by the constants of <code>Hoa\Console\Processus</code>:
  <code>SIGHUP</code>, <code>SIGINT</code>, <code>SIGQUIT</code>,
  <code>SIGABRT</code>, <code>SIGKILL</code>, <code>SIGALRM</code> and
  <code>SIGTERM</code> (by default). Several <strong>signals</strong> can be
  send to the processus in order to stop them. To get the detail, please, see
  <a href="http://freebsd.org/cgi/man.cgi?query=signal"
     title="signal(3), FreeBSD Library Functions Manual">the
     <code>signal</code></a> page.</p>

  <h3 id="Miscellaneous" for="main-toc">Miscellaneous</h3>

  <p>The <code>getTitle</code> and <code>setTitle</code> static methods on the
  <code>Hoa\Console\Processus</code> class respectively allow to get and set the
  title of the processus. Thus:</p>
  <pre><code class="language-php">Hoa\Console\Processus::setTitle('hoa #1');</code></pre>
  <p>And in another terminal:</p>
  <pre data-line="2"><code class="language-shell">$ ps | grep hoa
69578 ttys006    0:00.01 hoa #1
70874 ttys008    0:00.00 grep hoa</code></pre>
  <p>These methods are really useful when we manipulate a lot of processus and
  we would like to identify them efficiently (for example with tools like
  <code>top</code> or <code>ps</code>). Note that they are working only if you
  have at least PHP5.5.</p>
  <p>Another interesting static method is
  <code>Hoa\Console\Processus::locate</code> that allows to determine the path
  to a given program. For example:</p>
  <pre><code class="language-php">var_dump(Hoa\Console\Processus::locate('php'));

/**
 * Could output:
 *     string(12) "/usr/bin/php"
 */</code></pre>
  <p>In the case where the program is not found, <code>null</code> will be
  returned. This method is based on the <code>PATH</code> of your system.</p>

  <h3 id="Interactive_processus_and_pseudo-terminals" for="main-toc">Interactive
  processus and pseudo-terminals</h3>

  <p>This section is a little bit technical but it explains a
  <strong>problem</strong> that can be met with some processus called
  <strong>interactive</strong>.</p>
  <p>The <code>Hoa\Console\Processus</code> class allows to automate the
  interaction with processus very easily. However, it is not always possible to
  create such an automation because of the behavior of the processus. We will
  illustrate the problem by writing the <code>Interactive.php</code> file:</p>
  <pre><code class="language-php">&amp;lt;?php

echo 'Login: ';

if (false === $login = fgets(STDIN)) {
    fwrite(STDERR, 'Hmm, no login.' . "\n");
    exit(1);
}

echo 'Password: ';

if (false === $password = fgets(STDIN)) {
    fwrite(STDERR, 'Hmm, no password.' . "\n");
    exit(2);
}

echo 'Result:', "\n\t", $login, "\t", $password;</code></pre>
  <p>Let's execute this processus to see what it does:</p>
  <pre><code class="language-shell">$ php Interactive.php
Login: myLogin
Password: myPassword
Result:
    myLogin
    myPassword</code></pre>
  <p>And now, let's automate the execution of this processus:</p>
  <pre><code class="language-shell">$ echo 'myLogin\nmyPassword' > data
$ php Interactive.php &amp;lt; data
Login: Password: Result:
    myLogin
    myPassword</code></pre>
  <p>Excellent. We could easily get the same result with
  <code>Hoa\Console\Processus</code>. Now, if our processus want to ensure that
  <code>STDIN</code> is empty between two inputs, it can add:</p>
  <pre data-line-offset="7" data-line="10"><code class="language-php">}

fseek(STDIN, 0, SEEK_END);

echo 'Password: ';</code></pre>
  <p>And then in this case, if we try to automate the execution:</p>
  <pre><code class="language-shell">$ php Interactive.php &amp;lt; data
Login: Password: Hmm, no password.</code></pre>
  <p>This is absolutely a normal behavior, but
  <code>Hoa\Console\Processus</code> can do nothing to solve this issue.</p>
  <p>The solution would be to use a
  <a href="https://en.wikipedia.org/wiki/Pseudo_terminal">pseudo-terminal</a> by
  using the PTY functions (please, see
  <a href="http://kernel.org/doc/man-pages/online/pages/man7/pty.7.html"
     title="pty(7), Linux Programmer's Manual">in Linux</a> or
  <a href="http://freebsd.org/cgi/man.cgi?query=pty"
     title="pty(3), FreeBSD Library Functions Manual" >in FreeBSD</a>).
  Unfortunately these functions are not available in PHP for technical reasons.
  There is no possible solutions in pure PHP, but it is still conceivable to use
  an <strong>external</strong> program, written in C for example.</p>

  <h2 id="Conclusion" for="main-toc">Conclusion</h2>

  <p>The <code>Hoa\Console</code> library provides
  <strong>comprehensive</strong> tools to write programs tailored to a
  <strong>textual</strong> interface, whether it be for interaction with the
  window or the cursor, the interaction with the user thanks to a very
  customizable readline (with autocompletion and shortcuts), the options reading
  for programs themselves, the construction of elaborated programs, or even the
  execution, interaction and communication with processus.</p>

</yield>
</overlay>