Table of Contents
NAME
Gzz::Text::Utils
AUTHOR
Francis Grizzly Smit (grizzly@smit.id.au)
VERSION
v0.1.23
TITLE
Gzz::Text::Utils
SUBTITLE
A Raku module to provide text formatting services to Raku programs.
COPYRIGHT
LGPL V3.0+ LICENSE
Introduction
A Raku module to provide text formatting services to Raku programs.
Including a sprintf front-end Sprintf that copes better with Ansi highlighted text and implements %U
and does octal as 0o123
or 0O123
if you choose %O
as I hate ambiguity like 0123
is it an int with leading zeros or an octal number. Also there is %N
for a new line and %T
for a tab helpful when you want to use single quotes to stop the $
specs needing back slashes.
And a printf
alike Printf
.
Also it does centring and there is a max-width
field in the %
spec i.e. %*.*.*E
, and more.
Top of Document
Motivations
When you embed formatting information into your text such as bold, italics, etc ... and colours standard text formatting will not work e.g. printf, sprintf etc also those functions don't do centring.
Another important thing to note is that even these functions will fail if you include such formatting in the text field unless you supply a copy of the text with out the formatting characters in it in the :ref field i.e. left($formatted-text, $width, :ref($unformatted-text))
or text($formatted-text, $width, :$ref)
if the reference text is in a variable called $ref
or you can write it as left($formatted-text, $width, ref => $unformatted-text)
Top of Document
Update
Fixed the proto type of left
etc is now
sub left(Str:D $text, Int:D $width is copy, Str:D $fill = ' ',
:&number-of-chars:(Int:D, Int:D --> Bool:D) = &left-global-number-of-chars,
Str:D :$ref = strip-ansi($text), Int:D
:$max-width = 0, Str:D :$ellipsis = '' --> Str) is export
Where sub strip-ansi(Str:D $text --> Str:D) is export
is my new function for striping out ANSI escape sequences so we don't need to supply :$ref
unless it contains codes that sub strip-ansi(Str:D $text --> Str:D) is export
cannot strip out, if so I would like to know so I can update it to cope with these new codes.
Top of Document
Exceptions
BadArg
class BadArg is Exception is export
BadArg is a exception type that Sprintf will throw in case of badly specified arguments.
Top of Document
ArgParityMissMatch
class ArgParityMissMatch is Exception is export
ArgParityMissMatch is an exception class that Sprintf throws if the number of arguments does not match what the number the format string says there should be.
NB: if you use num$
argument specs these will not count as they grab from the args add hoc, *
width and precision spec however do count as they consume argument.
Top of Document
class FormatSpecError is Exception is export
FormatSpecError is an exception class that Format (used by Sprintf) throws if there is an error in the Format specification (i.e. %n
instead of %N
as %n
is already taken, the same with using %t
instead of %T
).
Or anything else wrong with the Format specifier.
NB: %N
introduces a \n
character and %T
a tab (i.e. \t
).
Top of Document
Format & FormatActions are a grammar and Actions pair that parse out the % spec and normal text chunks of a format string.
For use by Sprintf a sprintf alternative that copes with ANSI highlighted text.
Top of Document
UnhighlightBase
& UnhighlightBaseActions
and Unhighlight
& UnhighlightActions
UnhighlightBase
& UnhighlightBaseActions
are a grammar & role pair that does the work required to to parse apart ansi highlighted text into ANSI highlighted and plain text.
Unhighlight
& UnhighlightActions
are a grammar & class pair which provide a simple TOP for applying an application of UnhighlightBase
& UnhighlightBaseActions
for use by sub strip-ansi(Str:D $text --
Str:D) is export> to strip out the plain text from a ANSI formatted string
Top of Document
The Functions Provided
strip-ansi
sub strip-ansi(Str:D $text --> Str:D) is export
Strips out all the ANSI escapes, at the moment just those provided by the Terminal::ANSI
or Terminal::ANSI::OO
modules both available as Terminal::ANSI
from zef etc I am not sure how exhaustive that is, but I will implement any more escapes as I become aware of them.
hwcswidth
sub hwcswidth(Str:D $text --> Int:D) is export
Same as wcswidth
but it copes with ANSI escape sequences unlike wcswidth
.
Top of Document
Here are 4 functions provided to centre
, left
and right
justify text even when it is ANSI formatted.
centre
⋄
Centring text in a field.
sub centre(Str:D $text,
Int:D $width is copy,
Str:D $fill = ' ',
:&number-of-chars:(Int:D, Int:D --> Bool:D) =
¢re-global-number-of-chars,
Str:D :$ref = strip-ansi($text),
Int:D :$max-width = 0,
Str:D :$ellipsis = '' --> Str) is export {
Top of Document
left
⋄
Left Justifying text.
sub left(Str:D $text, Int:D $width is copy, Str:D $fill = ' ',
:&number-of-chars:(Int:D, Int:D --> Bool:D) = &left-global-number-of-chars,
Str:D :$ref = strip-ansi($text), Int:D :$max-width = 0,
Str:D :$ellipsis = '' --> Str) is export
left
is the same except that except that it puts all the padding on the right of the field.
Top of Document
right
⋄
Right justifying text.
sub right(Str:D $text, Int:D $width is copy, Str:D $fill = ' ',
:&number-of-chars:(Int:D, Int:D --> Bool:D) = &right-global-number-of-chars,
Str:D :$ref = strip-ansi($text), Int:D :$max-width = 0,
Str:D :$ellipsis = '' --> Str) is export
text
Cropping Text in a field.
sub crop-field(Str:D $text,
Int:D $w is rw,
Int:D $width is rw,
Bool:D $cropped is rw,
Int:D $max-width,
Str:D :$ellipsis = '' --> Str:D) is export {
Top of Document
Sprintf
Sprintf like sprintf only it can deal with ANSI highlighted text. And has lots of other options, including the ability to specify a $max-width
using width.precision.max-width
, which can be .*
, *<num>$
, .*
, or <num>
sub Sprintf(Str:D $format-str,
:&number-of-chars:(Int:D, Int:D --> Bool:D) =
&Sprintf-global-number-of-chars,
Str:D :$ellipsis = '',
*@args --> Str) is export
Where:
format-str
is is a superset of the sprintf
format string, but it has extra features: like the flag [ <char> ]
where can be almost anything except [
, ]
control characters, white space other than the normal space, and max-width
after the precision.
The format string looks like this:
token format { <chunks>+ }
token chunks { [ <chunk> || '%' <format-spec> ] }
token chunk { <-[%]>+ }
token format-spec { [ <fmt-esc> || <fmt-spec> ] }
token fmt-esc { [ '%' #`« a literal % »
|| 'N' #`« a nl i.e. \n char but does not require interpolation so no double quotes required »
|| 'T' #`« a tab i.e. \t char but does not require interpolation so no double quotes required »
|| 'n' #`« not implemented and will not be, throws an exception if matched »
|| 't' #`« not implemented and will not be, throws an exception if matched »
]
}
token fmt-spec { [ <dollar-directive> '$' ]? <flags>? <width>? [ '.' <precision> [ '.' <max-width> ]? ]? <modifier>? <spec-char> }
Top of Document
Where
dollar-directive
is a integer >= 1
flags
is any zero or more of:
+
put a plus in front of positive values.
-
left justify, right is the default
^
centre justify.
#
ensure the leading 0
for any octal, prefix non-zero hexadecimal with 0x
or 0X
, prefix non-zero binary with 0b
or 0B
v
vector flag (used only with d directive)
' '
pad with spaces.
0
pad with zeros.
[ <char> ]
pad with character char where char matches:
<-[ <cntrl> \s \[ \] ]> || ' '
i.e. anything except control characters, white space (apart from the basic white space (i.e. \x20 or the one with ord 32)), and [
and finally ]
.
Top of Document
width
is either an integer or a *
or a *
followed by an integer >= 1 and a '$'.
precision
is a .
followed by either an positive integer or a *
or a *
followed by an integer >= 1 and a '$'.
max-width
is a .
followed by either an positive integer or a *
or a *
followed by an integer >= 1 and a '$'.
modifier
These are not implemented but is one of:
hh
interpret integer as a type char
or unsigned char
.
h
interpret integer as a type short
or unsigned short
.
j
interpret integer as a type intmax_t
, only with a C99 compiler (unportable).
l
interpret integer as a type long
or unsigned long
.
ll
interpret integer as a type long long
, unsigned long long
, or quad
(typically 64-bit integers).
q
interpret integer as a type long long
, unsigned long long
, or quad
(typically 64-bit integers).
L
interpret integer as a type long long
, unsigned long long
, or quad
(typically 64-bit integers).
t
interpret integer as a type ptrdiff_t
.
z
interpret integer as a type size_t
.
Top of Document
spec-char
or the conversion character is one of:
c
a character with the given codepoint.
s
a string.
d
a signed integer, in decimal.
u
an unsigned integer, in decimal.
o
an unsigned integer, in octal, with a 0o
prepended if the #
flag is present.
x
an unsigned integer, in hexadecimal, with a 0x
prepended if the #
flag is present.
e
a floating-point number, in scientific notation.
f
a floating-point number, in fixed decimal notation.
g
a floating-point number, in %e or %f notation.
X
like x
, but using uppercase letters, with a 0X
prepended if the #
flag is present.
E
like e
, but using an uppercase E
.
G
like g
, but with an uppercase E
(if applicable).
b
an unsigned integer, in binary, with a 0b
prepended if the #
flag is present.
B
an unsigned integer, in binary, with a 0B
prepended if the #
flag is present.
i
a synonym for %d
.
D
a synonym for %ld
.
U
a synonym for %lu
.
O
a synonym for %lo
.
F
a synonym for %f
.
Top of Document
:&number-of-chars
is an optional named argument which takes a function with a signature :(Int:D, Int:D --
Bool:D)> if not specified it will have the value of &Sprintf-global-number-of-chars
which is defined as:
our $Sprintf-total-number-of-chars is export = 0;
our $Sprintf-total-number-of-visible-chars is export = 0;
sub Sprintf-global-number-of-chars(Int:D $number-of-chars, Int:D $number-of-visible-chars --> Bool:D) {
$Sprintf-total-number-of-chars = $number-of-chars;
$Sprintf-total-number-of-visible-chars = $number-of-visible-chars;
return True
}
This is exactly the same as the argument by the same name in centre
, left
and right
above.
i.e.
sub test( --> True) is export {
...
...
...
my $test-number-of-chars = 0;
my $test-number-of-visible-chars = 0;
sub test-number-of-chars(Int:D $number-of-chars, Int:D $number-of-visible-chars --> Bool:D) {
$test-number-of-chars = $number-of-chars;
$test-number-of-visible-chars = $number-of-visible-chars;
return True
}
put Sprintf('%30.14.14s, %30.14.13s%N%%%N%^*.*s%3$*4$.*3$.*6$d%N%2$^[&]*3$.*4$.*6$s%T%1$[*]^100.*4$.99s',
${ arg => $highlighted, ref => $text }, $text, 30, 14, $highlighted, 13,
:number-of-chars(&test-number-of-chars), :ellipsis('…'));
dd $test-number-of-chars, $test-number-of-visible-chars;
put Sprintf('%30.14.14s, testing %30.14.13s%N%%%N%^*.*s%3$*4$.*3$.*6$d%N%2$^[&]*3$.*4$.*6$s%T%1$[*]^100.*4$.99s',
$[ $highlighted, $text ], $text, 30, 14, $highlighted, 13, 13,
:number-of-chars(&test-number-of-chars), :ellipsis('…'));
dd $test-number-of-chars, $test-number-of-visible-chars;
...
...
...
}
- Note: This is a closure we should always use a closure if we want to get the number of characters printed.
Top of Document
:$ellipsis
this is an optional argument of type Str:D
which defaults to ''
, if set will be used to mark elided text, if the argument is truncated due to exceeding the value of max-width
(note max-width
defaults to 0
which means infinity). The recommended value would be something like …
.
*@args
is an arbitrary long list of values each argument can be either a scalar value to be printed or a Hash or an Array
If a Hash then it should contain two pairs with keys: arg
and ref
; denoting the actual argument and a reference argument respectively, the ref argument should be the same as arg
but with no ANSI formatting etc to mess up the counting. As this ruins formatting spacing. If not present will be set to strip-ansi($arg)
, only bother with all this if strip-ansi($arg)
isn't good enough.
If a Array then it should contain two values. The first being arg
and the other being ref
; everything else is the same as above.
arg
the actual argument.
@args[$i][]
the actual argument. Where $i
is the current index into the array of args.
@args[$i][1]
the reference argument, as in the :$ref
arg of the left, right and centre functions which it uses. It only makes sense if your talking strings possibly formatted if not present will be set to strip-ansi($arg)
if $arg is a Str or just $arg otherwise.
If it's a scalar then it's the argument itself. And $ref
is strip-ansi($arg)
if $arg is a string type i.e. Str or just C$arg>> otherwise.
ref
the reference argument, as in the :$ref
arg of the left, right and centre functions which it uses. It only makes sense if your talking strings possibly formatted if not present will be set to strip-ansi($arg)
if $arg is a Str or just $arg otherwise.
i.e.
put Sprintf('%30.14.14s, %30.14.13s%N%%%N%^*.*s%3$*4$.*3$.*6$d%N%2$^[&]*3$.*4$.*6$s%T%1$[*]^100.*4$.99s',
${ arg => $highlighted, ref => $text }, $text, 30, 14, $highlighted, 13,
:number-of-chars(&test-number-of-chars), :ellipsis('…'));
dd $test-number-of-chars, $test-number-of-visible-chars;
put Sprintf('%30.14.14s, testing %30.14.13s%N%%%N%^*.*s%3$*4$.*3$.*6$d%N%2$^[&]*3$.*4$.*6$s%T%1$[*]^100.*4$.99s',
$[ $highlighted, $text ], $text, 30, 14, $highlighted, 13, 13,
:number-of-chars(&test-number-of-chars), :ellipsis('…'));
dd $test-number-of-chars, $test-number-of-visible-chars;
Top of Document
Printf
Top of Document
MultiT
A lot of types but not Any.
subset MultiT is export of Any where * ~~ Str | Int | Rat | Num | Bool | Array;
Display a text based menu.
sub 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,
:&value:(Int:D $c, @a --> MultiT) = &default-value,
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(: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.
Top of Document
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.
&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(: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.
Top of Document
dropdown(…)
A text based dropdown/list or menu with ANSI colours.
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.
Here is an example of use.
Top of Document
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
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
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.
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
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.
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
dots(…)
Returns $text
in a field of $width
with a line of dots preceding it. Sort of like left
with $fill
defaulting to .
.
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