### ----------------------------------------------------
### -- Gzz::Text::Utils
### -- Licenses: LGPL-3.0-or-later
### -- Authors: Francis Grizzly Smit <grizzly@smit.id.au>
### -- File: README.md
### ----------------------------------------------------
### -- Chunk 2 of 2
 2).

        * **`$bg-colour1`** is the background colour of the row (i.e. $c % 2 != 0 or not $c %% 2).

        * **`$fg-colour1`** is the foreground colour of the row (i.e. $c % 2 != 0).

    * **`&value`** is a callback to get the return value for the function.

        * **`$c`** is the row selected.

        * **`$c`** is the array @candidates.

    * **`:c(:color(:$colour))`** defines a boolean flag to tell whether to use colours or not.

      * you can use **`:c`**, **`:color`** or **`:colour`** for this they are all exactly the same.

    * **`:s(:$syntax)`** same as **`$colour`** except it could result in some sort of syntax highlighting. 

    * **`$highlight-bg-colour`** the background colour to use to highlight the current line.

    * **`$highlight-fg-colour`** the foreground colour to use to highlight the current line.

    * **`$bg-colour0`** the background colour to use if the line count is divisible by 2.

    * **`$fg-colour0`** the foreground colour to use if the line count is divisible by 2.

    * **`$bg-colour1`** the background colour to use if the line count is not divisible by 2.

    * **`$fg-colour1`** the foreground colour to use if the line count is not divisible by 2.

    * **`$bg-prompt`** the background colour to use on the prompt line below the selection area.

    * **`$fg-prompt`** the foreground colour to use on the prompt line below the selection area.

    * **`$wrap-around`** if true then the selection area wraps around, (i.e going past the end wraps around, instead of refusing to go there).

      * **`$highlight-bg-colour`** to **`$wrap-around`** are all just used for the dropdown case (i.e. **`$colour`** or **`$syntax`** are True)

      * **`$syntax`** is no different from **`$colour`** unless the user defines it using the **`:&row`** parameter.

        * calls [dropdown](#dropdown) to do the colour work.

[Top of Document](#table-of-contents)

### input-menu(…)

```raku
sub input-menu(@candidates is copy, Str:D $message = "",
                              :&row:(Int:D $c, Int:D $p, @a,
                                     Bool:D :$colour = False, Bool:D :$syntax = False,
                                     Str:D :$highlight-bg-colour = '', Str:D :$highlight-fg-colour = '',
                                     Str:D :$bg-colour0 = '', Str:D :$fg-colour0 = '', 
                                     Str:D :$bg-colour1 = '', Str:D :$fg-colour1 = '' --> Str:D) = &default-row-input-menu, 
                              :&value:(Int:D $c, @a --> MultiT) = &default-value, 
                              :&elt-prompt:(Int:D $c, @a,
                                     Bool:D :$colour = False, Bool:D :$syntax = False,
                                     Str:D :$bg-prompt = '', Str:D :$fg-prompt = '' --> Str:D)  = &default-prompt,
                              :&edit:(Int:D $c, @a is copy, Str:D $e --> Bool:D) = &default-edit, 
                              Bool:D :c(:color(:$colour)) is copy = False,
                              Bool:D :s(:$syntax) = False, 
                              Str:D :$highlight-bg-colour = t.bg-color(0, 0, 127) ~ t.bold, 
                              Str:D :$highlight-fg-colour = t.bright-yellow, 
                              Str:D :$bg-colour0 = t.bg-yellow ~ t.bold, 
                              Str:D :$fg-colour0 = t.bright-blue, 
                              Str:D :$bg-colour1 = t.bg-color(0, 127, 0) ~ t.bold, 
                              Str:D :$fg-colour1 = t.bright-blue,  
                              Str:D :$bg-prompt = t.bg-green ~ t.bold, 
                              Str:D :$fg-prompt = t.bright-blue, 
                              Bool:D :$wrap-around = False --> MultiT) is export
```

  * Where:

    * **`@candidates`** is an array of hashes to make up the rows of the menu.

    * **`$message`** is a message to be displayed at the top of the ascii text form of things (i.e. no colourising).

    * **`&row`** is is a callback to deal with the rows of the menu.

      * Where

        * **`$c`** is the current row count.

        * **`$p`** is the current position in the @candidates array.

        * **`@a`** is the array @candidates itself.

        * **`$highlight-bg-colour`** is the background colour of the current row (i.e. $c == $p).

        * **`$highlight-fg-colour`** is the foreground colour of the current row (i.e. $c == $p).

        * **`$bg-colour0`** is the background colour of the row (i.e. $c %% 2).

        * **`$fg-colour0`** is the foreground colour of the row (i.e. $c %% 2).

        * **`$bg-colour1`** is the background colour of the row (i.e. $c % 2 != 0 or not $c %% 2).

        * **`$fg-colour1`** is the foreground colour of the row (i.e. $c % 2 != 0).

    * **`&value`** is a callback to get the return value for the function.

        * **`$c`** is the row selected.

        * **`$c`** is the array @candidates.

    * **`&elt-prompt:(Int:D $c, @a, Bool:D :$colour = False, Bool:D :$syntax = False, Str:D :$bg-prompt = '', Str:D :$fg-prompt = '' --> Str:D) = &default-prompt`** 

      The callback called by the function to get the prompts to let the user edit the value of the row.

      * **`$c`** is the entry choosen by the user.

      * **`@a`** is the candidates array.

      * **`:c(:color(:$colour))`** defines a boolean flag to tell whether to use colours or not.

        * you can use **`:c`**, **`:color`** or **`:colour`** for this they are all exactly the same.

      * **`:s(:$syntax)`** same as **`$colour`** except it could result in some sort of syntax highlighting. 

      * **`$bg-prompt`** the background colour to use on the prompt line below the selection area.

      * **`$fg-prompt`** the foreground colour to use on the prompt line below the selection area.

    * **`&edit:(Int:D $c, @a is copy, Str:D $e --> Bool:D) = &default-edit`**

      The callback called by the function to set the new value of the row.

      * **`$c`** is the entry choosen by the user.

      * **`@a`** is the candidates array.

    * **`:c(:color(:$colour))`** defines a boolean flag to tell whether to use colours or not.

      * you can use **`:c`**, **`:color`** or **`:colour`** for this they are all exactly the same.

    * **`:s(:$syntax)`** same as **`$colour`** except it could result in some sort of syntax highlighting. 

    * **`$highlight-bg-colour`** the background colour to use to highlight the current line.

    * **`$highlight-fg-colour`** the foreground colour to use to highlight the current line.

    * **`$bg-colour0`** the background colour to use if the line count is divisible by 2.

    * **`$fg-colour0`** the foreground colour to use if the line count is divisible by 2.

    * **`$bg-colour1`** the background colour to use if the line count is not divisible by 2.

    * **`$fg-colour1`** the foreground colour to use if the line count is not divisible by 2.

    * **`$bg-prompt`** the background colour to use on the prompt line below the selection area.

    * **`$fg-prompt`** the foreground colour to use on the prompt line below the selection area.

    * **`$wrap-around`** if true then the selection area wraps around, (i.e going past the end wraps around, instead of refusing to go there).

      * **`$highlight-bg-colour`** to **`$wrap-around`** are all just used for the dropdown case (i.e. **`$colour`** or **`$syntax`** are True)

      * **`$syntax`** is no different from **`$colour`** unless the user defines it using the **`:&row`** parameter.

        * calls [dropdown](#dropdown) to do the colour work.

        * **NB: the colours stuff is not yet implemented**

[Top of Document](#table-of-contents)

### dropdown(…)

A text based dropdown/list or menu with ANSI colours.

```raku
sub dropdown(MultiT:D $id, Int:D $window-height is copy, Str:D $id-name,
                        &setup-option-str:(Int:D $c, Int:D $p, @a --> Str:D),
                        &find-pos:(MultiT $r, Int:D $p, @a --> Int:D),
                        &get-result:(MultiT:D $res, Int:D $p, Int:D $l, @a --> MultiT:D),
                        @array,
                        Str:D :$highlight-bg-colour = t.bg-color(0, 0, 127) ~ t.bold, 
                        Str:D :$highlight-fg-colour = t.bright-yellow, 
                        Str:D :$bg-colour0 = t.bg-yellow ~ t.bold, 
                        Str:D :$fg-colour0 = t.bright-blue, 
                        Str:D :$bg-colour1 = t.bg-color(0, 127, 0) ~ t.bold, 
                        Str:D :$fg-colour1 = t.bright-blue,  
                        Str:D :$bg-prompt = t.bg-green ~ t.bold, 
                        Str:D :$fg-prompt = t.bright-blue, 
                        Bool:D :$wrap-around = False --> MultiT) is export
```

  * Where

    * **`$id`** is the starting value of our position in the array/choices.

    * **`$window-height`** is the number of rows of characters to display at a time.

    * **`$id-name`** is the name of the parameter we are scrolling.

    * **`&setup-option-str`** is a function that returns the current row.

      * Where:

        * the arg **`$c`** will be the count of the row we are drawing.

        * the arg **`$p`** will be the position in the array we are at. 

        * the arg **`@a`** will be the **`@array`** supplied to **`dropdown(…)`** 

          * the use of a function for this means you can compute a much more complex field.

    * **`&find-pos`** is a function that finds the start position in the **`dropdown`**.

      * Where:

        * the arg **`$r`** is the value in the array **`@array`** to look for.

        * the arg **`$p`** is the best approximation of where it might be if you are using it in a loop or something it could be where it last was. 

        * the arg **`@a`** the argument **`@array`** that was passed to **`dropdown`**.

          * you can name these argument anything you like in you function, and because of the computed nature of this function and the other two you have great flexibility.

    * **`&get-result`** is a function to work out the value selected.

      * Where:

        * the arg **`$res`** is the default value to return.

        * the arg **`$p`** is the current position in the array **`@array`** supplied to **`dropdown`**.

        * the arg **`$l`** is the length of the array **`@array`**.

        * the arg **`@a`** is the array **`@array`** that was supplied to **`dropdown`**.

    * **`@array`** the array of rows to display.

    * **`$highlight-bg-colour`** the background colour to use to highlight the current line.

    * **`$highlight-fg-colour`** the foreground colour to use to highlight the current line.

    * **`$bg-colour0`** the background colour to use if the line count is divisible by 2.

    * **`$fg-colour0`** the foreground colour to use if the line count is divisible by 2.

    * **`$bg-colour1`** the background colour to use if the line count is not divisible by 2.

    * **`$fg-colour1`** the foreground colour to use if the line count is not divisible by 2.

    * **`$bg-prompt`** the background colour to use on the prompt line below the selection area.

    * **`$fg-prompt`** the foreground colour to use on the prompt line below the selection area.

    * **`$wrap-around`** if true then the selection area wraps around, (i.e going past the end wraps around, instead of refusing to go there).

      * Because we use a function we can compute much more complex results; depending on what we have in **`@array`**. The result can be any of Str, Int, Rat or Num see [MultiT](#multit).

Here is an example of use.

[Top of Document](#table-of-contents)

```raku
my &setup-option-str = sub (Int:D $cnt, Int:D $p, @array --> Str:D ) {
    my Str $name;
    my Str $cc;
    my Str $flag;
    my Str $prefix;
    if $cnt < 0 {
        $name   = "No country selected yet.";
        $cc     = "";
        $flag   = "";
        $prefix = "you must choose one";
    } else {
        my %row = @array[$cnt];
        $name   = %row«_name»;
        $cc     = %row«cc»;
        try {
            CATCH {
                default {
                    my $Name = $name;
                    $Name ~~ s:g/ <wb> 'and' <wb> /\&/;
                    try {
                        CATCH {
                            default { $flag = uniparse 'PENGUIN'}
                        }
                        $flag = uniparse $Name;
                    }
                }
            }
            $flag   = uniparse $name;
        }
        $prefix = %row«prefix»;
    }
    return "$flag $name: $cc ($prefix)"
};
my &find-pos = sub (MultiT $result, Int:D $pos, @array --> Int:D) {
    for @array.kv -> $idx, %r {
        if %r{$id-name} == $result {
            $pos = $idx;
            last; # found so don't waste resources #
        }
    }
    return $pos;
}
my &get-result = sub (MultiT:D $result, Int:D $pos, Int:D $length, @array --> MultiT:D ) {
    my $res = $result;
    if $pos ~~ 0..^$length {
      my %row = |%(@array[$pos]);
      $res = %row«id» if %row«id»:exists;
    }
    return $res
};
my Int:D $cc-id        = dropdown($cc_id, 20, 'id',
                                    &setup-option-str, &find-pos, &get-result, @_country);
while !valid-country-cc-id($cc-id, %countries) {
    $cc-id             = dropdown($cc-id, 20, 'id',
                                    &setup-option-str, &find-pos, &get-result, @_country);
}
```

Or using a much simpler array. **NB: from `menu`**

[Top of Document](#table-of-contents)

```raku
my &setup-option-str = sub (Int:D $cnt, Int:D $pos, @array --> Str:D ) {
    return @array[$cnt];
};
my &get-result = sub (MultiT:D $result, Int:D $pos, Int:D $length, @array --> MultiT:D ) {
    my $res = $result;
    if $pos ~~ 0..^$length {
      $res = @array[$pos];
    }
    return $res
};
my &find-pos = sub (MultiT $result, Int:D $pos, @array --> Int:D) {
    for @array.kv -> $idx, $r {
        if $r eq $result {
            $pos = $idx;
            last; # found so don't waste resources #
        }
    }
    return $pos;
}
my Str:D $result = dropdown(@candidates[@candidates.elems - 1], 40, 'backup',
                                    &setup-option-str, &find-pos, &get-result, @candidates);
```

[Top of Document](#table-of-contents)

### lead-dots(…)

Returns **`$text`** in a field of **`$width`** with a line of dots preceding it. Sort of like **`left`** with **`$fill`** defaulting to **`.`** but with a single space between the text and the padding.

```raku
sub lead-dots(Str:D $text, Int:D $width is copy, Str:D $fill = '.' --> Str) is export
```

  * Where:

    * **`$text`** the text to be preceded by the dots.

    * **`$width`** the width of the total field.

    * **`$fill`** the fill char or string.

[Top of Document](#table-of-contents)

### trailing-dots(…)

Returns **`$text`** in a field of **`$width`** with a line of dots trailing after it. Sort of like **`right`** with **`$fill`** defaulting to **`.`** but with a single space between the text and the padding.

```raku
sub trailing-dots(Str:D $text, Int:D $width is copy, Str:D $fill = '.' --> Str) is export
```

  * Where:

    * **`$text`** the text to be trailed by the dots.

    * **`$width`** the width of the total field.

    * **`$fill`** the fill char or string.

[Top of Document](#table-of-contents)

### dots(…)

Returns **`$text`** in a field of **`$width`** with a line of dots preceding it. Sort of like **`left`** with **`$fill`** defaulting to **`.`**.

```raku
sub dots(Str:D $text, Int:D $width is copy, Str:D $fill = '.' --> Str) is export
```

  * Where:

    * **`$text`** the text to be preceded by the dots.

    * **`$width`** the width of the total field.

    * **`$fill`** the fill char or string.

[Top of Document](#table-of-contents)



