## dist_cpan-SOFTMOTH-Template-Mustache.md
[![Build Status](https://travis-ci.org/softmoth/raku-Template-Mustache.svg?branch=master)](https://travis-ci.org/softmoth/raku-Template-Mustache) [![Windows Status](https://ci.appveyor.com/api/projects/status/github/softmoth/raku-Template-Mustache?branch=master&passingText=Windows%20-%20OK&failingText=Windows%20-%20FAIL&pendingText=Windows%20-%20pending&svg=true)](https://ci.appveyor.com/project/softmoth/raku-Template-Mustache/branch/master)

Raku implementation of Mustache templates, <http://mustache.github.io/>.

# Synopsis

```
use Template::Mustache;

# Call .render as a class method
Template::Mustache.render('Hello, {{planet}}!', { planet => 'world' }).say;

# Or instantiate an instance
my $stache = Template::Mustache.new: :from<./views>;

# Subroutines are called
say $stache.render('The time is {{time}}', {
    time => { ~DateTime.new(now).local }
});

my @people =
    { :name('James T. Kirk'), :title<Captain> },
    { :name('Wesley'), :title('Dread Pirate'), :emcee },
    { :name('Dana Scully'), :title('Special Agent') },
    ;

# See this template in ./t/views/roster.mustache
$stache.render('roster', { :@people }).say;

my %context =
    event => 'Masters of the Universe Convention',
    :@people,
    ;
my %partials =
    welcome =>
        qq:b{Welcome to the {{event}}! We’re pleased to have you here.\n\n},
    ;

# See this result in ./t/50-readme.t
Template::Mustache.render(q:to/EOF/,
        {{> welcome}}
        {{> roster}}

            Dinner at 7PM in the Grand Ballroom. Bring a chair!
        EOF
    %context,
    :from([%partials, './views'])
).say;

```

# Description

## Logging

### Log levels

Messages are logged with varying severity levels (from most to least severe): `Fatal`, `Error`, `Warn`, `Info`, `Verbose`, `Audit`, `Debug`, `Trace`, `Trace2`

By default, only messages of `Error` or worse are logged. That default can be changed with the `TEMPLATE_MUSTACHE_LOGLEVEL` environment variable.

```
TEMPLATE_MUSTACHE_LOGLEVEL=Debug

```

The default is overridden with the `:log-level` option to `Template::Mustache.new`, or a `Template::Mustache::Logger` object can be passed via the `:logger` option.

```
my $stache = Template::Mustache.new: :log-level<Trace>;

my $logger = Template::Mustache::Logger.new: :level<Debug>;
my $stache = Template::Mustache.new: :$logger;

```

Either method can be used with the `.render` method, as well.

```
my %data = hello => 'world';

Template::Mustache.render: 'Hello, {{hello}}!', %data, :log-level<Trace>;

my $logger = Template::Mustache::Logger.new: :level<Debug>;
Template::Mustache.render: 'Hello, {{hello}}!', %data, :$logger;

```

### Log routine

By default, any messages at level `Warn` or worse are logged with the `warn` routine. A `CONTROL` block can handle such warnings if needed; see [Language/phasers](https://docs.raku.org/language/phasers#CONTROL) for details. Less severe messages (`Info` and up) are logged with the `note` routine.

The routine can be set per log level, in the `Template::Mustache::Logger.routines` hash.

```
# Use say instead of note for Info and up; the more severe
# levels (C<Warn> down to C<Fatal>) still use the warn routine
my $stache = Template::Mustache.new: :log-routine(&say);

# But even those can be set explicitly
$stache.logger.routines{$_} = &die for <Warn Error Fatal>;

$stache.render: '{{missing}}', {};  # dies

```

### method log

* `multi method log(Exception $exception, LogLevel :$level)`
* `multi method log(LogLevel :$level, *@msgs)`

Emit a message at `$level` (`Info` by default).

# Extra features

## Template inheritence

Support for `hogan.js`-style [template inheritence](https://github.com/groue/GRMustache/blob/master/Guides/template_inheritance.md) is available.

## Pragma: KEEP-UNUSED-VARIABLES

Specify `:pragma<KEEP-UNUSED-VARIABLES>` to either `Template::Mustache.new` or `.render`, and any variables which are not defined in the data context will be kept in the rendered text. See `t/13-pragmas.t` for examples.

# More Examples and Tests

The Mustache spec provides a wealth of examples to demonstrate exactly how the format behaves.

<https://github.com/mustache/spec/tree/master/specs/>

All of the official Mustache spec tests pass. An updated copy of the tests is distributed in `t/specs`.

To check against the official specs repository, clone it into `../mustache-spec`:

```
git clone https://github.com/mustache/spec.git ../mustache-spec
prove -v -e 'raku -Ilib' t/

```

## Extra Specifications

The test file `t/specs/inheritable_partials.json` is taken from [groue/GRMustache](https:/github.com/groue/GRMustache).

# Other Mustache Implementations

There are many, many Mustache implementations in various languages. Some of note are:

* The original Ruby version <https://github.com/defunkt/mustache>
* Twitter's hogan.js <https://github.com/twitter/hogan.js>
* mustache.java <https://github.com/spullara/mustache.java>
* GRMustache (Objective C) <https://github.com/groue/GRMustache>
* mustache.php <https://github.com/bobthecow/mustache.php>

# TODO

* full object support (with method calls; currently the object is just stringified)
* global helpers (context items that float at the top of the stack)
* database loader
* pragmas (FILTERS?)

# License

[Artistic License 2.0](http://www.perlfoundation.org/artistic_license_2_0)


## dist_cpan-JMASLAK-Sys-Domainname.md
[![Build Status](https://travis-ci.org/jmaslak/Raku-Sys-Domainname.svg?branch=master)](https://travis-ci.org/jmaslak/Raku-Sys-Domainname)

# NAME

Sys::Domainname - Determine System Domain Name

# SYNOPSIS

```
use Sys::Domainname;

say "My domain name: {domainname}";

```

# DESCRIPTION

This module uses the `hostname -f` command (where it works) to determine the system's domain name.

If a domain name is not present, it returns an empty string. Should the `hostname -f` command fail, it returns a `Str` type object.

# WARNING

This module currently only works on Linux, OSX, and similar environments where the domain name is able to be determined with `hostname -f`.

In particular, this will always return `Str` on Windows.

# AUTHOR

Joelle Maslak [jmaslak@antelope.net](mailto:jmaslak@antelope.net)

# COPYRIGHT AND LICENSE

Copyright © 2020 Joelle Maslak

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## catpath.md
catpath

Combined from primary sources listed below.

# [In IO::Spec::Cygwin](#___top "go to top of document")[§](#(IO::Spec::Cygwin)_method_catpath "direct link")

See primary documentation
[in context](/type/IO/Spec/Cygwin#method_catpath)
for **method catpath**.

```raku
method catpath (Str:D $volume, Str:D $dir, Str:D $file --> Str:D)
```

Same as [`IO::Spec::Win32.catpath`](/type/IO/Spec/Win32#method_catpath), except will also change all backslashes to slashes at the end:

```raku
IO::Spec::Cygwin.catpath('C:', '/some/dir', 'foo.txt').say;
# OUTPUT: «C:/some/dir/foo.txt␤»

IO::Spec::Cygwin.catpath('C:', '/some/dir', '').say;
# OUTPUT: «C:/some/dir␤»

IO::Spec::Cygwin.catpath('', '/some/dir', 'foo.txt').say;
# OUTPUT: «/some/dir/foo.txt␤»

IO::Spec::Cygwin.catpath('E:', '', 'foo.txt').say;
# OUTPUT: «E:foo.txt␤»
```

# [In IO::Spec::Unix](#___top "go to top of document")[§](#(IO::Spec::Unix)_method_catpath "direct link")

See primary documentation
[in context](/type/IO/Spec/Unix#method_catpath)
for **method catpath**.

```raku
method catpath ($, Str:D $part1, Str:D $part2 --> Str:D)
```

Takes two path fragments and concatenates them, adding or removing a path separator, if necessary. The first argument is ignored (it exists to maintain consistent interface with other [`IO::Spec`](/type/IO/Spec) types for systems that have volumes).

```raku
IO::Spec::Unix.catpath($, 'some/dir', 'and/more').say;
# OUTPUT: «some/dir/and/more␤»
```

# [In IO::Spec::Win32](#___top "go to top of document")[§](#(IO::Spec::Win32)_method_catpath "direct link")

See primary documentation
[in context](/type/IO/Spec/Win32#method_catpath)
for **method catpath**.

```raku
method catpath (Str:D $volume, Str:D $dir, Str:D $file --> Str:D)
```

Concatenates a path from given volume, a chain of directories, and file. An empty string can be given for any of the three arguments. No attempt to make the path canonical is made. Use [`canonpath`](/routine/canonpath) for that purpose.

```raku
IO::Spec::Win32.catpath('C:', '/some/dir', 'foo.txt').say;
# OUTPUT: «C:/some/dir\foo.txt␤»

IO::Spec::Win32.catpath('C:', '/some/dir', '').say;
# OUTPUT: «C:/some/dir␤»

IO::Spec::Win32.catpath('', '/some/dir', 'foo.txt').say;
# OUTPUT: «/some/dir\foo.txt␤»

IO::Spec::Win32.catpath('E:', '', 'foo.txt').say;
# OUTPUT: «E:foo.txt␤»
```


## dist_cpan-JJATRIA-Timer-Stopwatch.md
## NAME

Timer::Stopwatch - Schedule and reset repeated time measurements

## SYNOPSIS

```
use Timer::Stopwatch;

my $irregular-supply = Supply.interval(1).grep: { Bool.pick }

my $timer = Timer::Stopwatch.new;
react {
    whenever $irregular-supply {
        note "{ now.DateTime.hh-mm-ss }: Received an irregular event";

        # Wait up to 2 seconds for the next event
        $timer.reset: 2;
    }
    whenever $timer {
        note "It's been { .round } seconds since the last event";
        $timer.stop;
    }
    whenever Promise.in: 20 {
        note 'Stopping after 20 seconds';
        $timer.stop;
    }
    whenever $timer.Promise {
        note "Timer was stopped. We're done";
        done;
    }
}

# OUTPUT:
# 20:33:39: Received an irregular event
# 20:33:40: Received an irregular event
# 20:33:42: Received an irregular event
# It's been 2 seconds since the last event
# Timer was stopped. We're done

```

## DESCRIPTION

Timer::Stopwatch is a resettable, stoppable wrapper around a Supply that can be used to mark multiple moments in time.

## METHODS

### in

```
method in(
    Numeric $in
) returns Timer::Stopwatch

```

Creates a new Stopwatch with a timer that will trigger in the given amount of seconds, unless it is reset or stopped before that.

### tick

```
method tick() returns Duration

```

Emits the duration since creation time (or the last `reset`) to the Supply. Returns the emitted Duration.

### reset

```
method reset(
    Numeric $in?
) returns Bool

```

Reset sets the start time for the stopwatch to the current time. If called with a numeric argument, it also sets a timer to expire after the given duration. It returns True if the call interrupted a pending timer, and False if no timer had been set, or if it had already expired, or if the stopwatch had already been stopped.

### stop

```
method stop() returns Bool

```

Stop marks this stopwatch as done. Once a stopwatch has been stopped, most of its actions are finished, and new stopwatch should be created. Internally, it stops any pending timers and closes the supply. It returns True if the call interrupted a pending timer, and False if no timer had been set, or if it had already expired, or if the stopwatch had already been stopped.

### Duration

```
method Duration() returns Duration

```

Returns the amount of time elapsed since the start (or the last reset) as a Duration.

### Promise

```
method Promise() returns Promise

```

Returns a Promise that will be kept when the Stopwatch is stopped. When kept, it will hold the Duration elapsed since the time the Stopwatch was created, or since the last call to `reset`.

### Supply

```
method Supply() returns Supply

```

Returns a live Supply that will receive timer events

## AUTHOR

José Joaquín Atria [jjatria@cpan.org](mailto:jjatria@cpan.org)

## COPYRIGHT AND LICENSE

Copyright 2020 José Joaquín Atria

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_cpan-SAMGWISE-Slang-Predicate.md
# NAME

Slang::Predicate - Predicates in perl6

# SYNOPSIS

```
use Slang::Predicate;

my (\α, \β) = (T, F);

say ((α → β) ∧ α) → β;

```

# DESCRIPTION

Slang::Predicate adds operators common to predicate logic directly to perl6.

Exported terms and operators are:

|  |  |  |
| --- | --- | --- |
| Terms | Term | Example |
| True | T | T ~~ True |
| False | F | F ~~ False |

|  |  |  |
| --- | --- | --- |
| Infix | operator | Example |
| True | T | T ~~ True |
| False | F | F ~~ False |
| Disjunction | ∨ | T ∨ F ~~ True |
| Conjunction | ∧ | T ∧ F ~~ False |
| Exclusive disjunction | ⊻ or ⊕ | T ⊻ F ~~ True |
| Conditional | → or ⇒ or ⊃ | T → F ~~ False |
| Biconditional | ↔ or ⇔ or ≡ | T ↔ F ~~ False |

|  |  |  |
| --- | --- | --- |
| Prefix | operator | Example |
| Negation | ¬ | ¬T ~~ False |
| Verum | ⊤ | ⊤F ~~ True |
| Falsum | ⊥ | ⊥T ~~ False |

# AUTHOR

Sam Gillespie [samgwise@gmail.com](mailto:samgwise@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2017 Sam Gillespie

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-wayland-Class-Loader-Dynamic.md
# Class::Loader::Dynamic

Will dynamically create classes with the same name as the modules. Modules can be specified with the glob language.

# Primary use: .load-module-pattern()

```
use	Class::Loader::Dynamic;

class Foo does Class::Loader::Dynamic {}

my $loader = Foo.new();
my ($passes, $fails) = $loader.load-module-pattern(
	:paths(['lib', 't']),
	:globs(["Lo?derTest*"]),
);
$passing-class = $passes<LoaderTestPassing>
$passing-class.the-method()

```

The above code will try to load eg. `LoaderTestPassing` and `LoaderTestFailing`, and even `LoZderTestZZZZZ`,
but will ignore `IgnoreLoaderTest`.

It will also call `.the-method` on the new object that's a `LoaderTestPassing`.

.load-module-pattern can also take a `:regexes` key that contains an array of regexes.
If a module matches any of the regexes or globs, then this will try to load the
class.

See `.available-modules` for info on the `:paths` option.

# .available-modules(@lib-paths)

Returns a list of all modules that could be loaded. The @lib-paths are the library
paths to search (eg. anything you declare with `use lib 'path'` will need to be
repeated here).

# .load-library(Str :$type, \*%parameters)

Loads the class specified in the `$type` string from the module of the same name.
%parameters are passed to the .new() method on the class.


## dist_zef-japhb-MUGS-Core.md
[![Actions Status](https://github.com/Raku-MUGS/MUGS-Core/workflows/test/badge.svg)](https://github.com/Raku-MUGS/MUGS-Core/actions)

# NAME

MUGS-Core - Core modules for MUGS (Multi-User Gaming Services)

# SYNOPSIS

```
# Setting up a simple MUGS-Core development environment
mkdir MUGS
cd MUGS
git clone git@github.com:Raku-MUGS/MUGS-Core.git
cd MUGS-Core
zef install --deps-only --exclude="pq:ver<5>:from<native>" .
raku -Ilib bin/mugs-admin create-universe

```

# DESCRIPTION

**NOTE: See the [top-level MUGS repo](https://github.com/Raku-MUGS/MUGS) for more info.**

MUGS-Core is the core of MUGS (Multi-User Gaming Services), a Raku-based platform for game service development. In other words, it is a set of basic services written in the Raku language for creating client-server and multi-user games. It abstracts away the boilerplate of managing player identities, tracking active games and sessions, sending and receiving messages and actions, and so forth.

This Proof-of-Concept release includes a WebSocket-based game server, simple admin and developer tools, and simple "games" intended primarily for testing. The game server can store data using either an internal ephemeral/test storage driver, or in SQLite databases on disk using a storage driver based on the Red ORM.

# ROADMAP

MUGS is still in its infancy, at the beginning of a long and hopefully very enjoyable journey. There is a [draft roadmap for the first few major releases](https://github.com/Raku-MUGS/MUGS/tree/main/docs/todo/release-roadmap.md) but I don't plan to do it all myself -- I'm looking for contributions of all sorts to help make it a reality.

# CONTRIBUTING

Please do! :-)

In all seriousness, check out [the CONTRIBUTING doc](docs/CONTRIBUTING.md) (identical in each repo) for details on how to contribute, as well as [the Coding Standards doc](https://github.com/Raku-MUGS/MUGS/tree/main/docs/design/coding-standards.md) for guidelines/standards/rules that apply to code contributions in particular.

The MUGS project has a matching GitHub org, [Raku-MUGS](https://github.com/Raku-MUGS), where you will find all related repositories and issue trackers, as well as formal meta-discussion.

More informal discussion can be found on IRC in Libera.Chat #mugs.

# AUTHOR

Geoffrey Broadwell [gjb@sonic.net](mailto:gjb@sonic.net) (japhb on GitHub and Libera.Chat)

# COPYRIGHT AND LICENSE

Copyright 2021-2024 Geoffrey Broadwell

MUGS is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-lizmat-Tie-Array.md
[![Actions Status](https://github.com/lizmat/Tie-Array/workflows/test/badge.svg)](https://github.com/lizmat/Tie-Array/actions)

# NAME

Raku port of Perl's Tie::Array module

# SYNOPSIS

```
use P5tie;
use Tie::Array;

```

# DESCRIPTION

This module tries to mimic the behaviour of Perl's `Tie::Array` module as closely as possible in the Raku Programming Language.

Tie::Array is a module intended to be subclassed by classes using the </P5tie|tie()> interface. It depends on the implementation of methods `FETCH`, `STORE`, `FETCHSIZE` and `STORESIZE`.

The `EXISTS` method should be implemented if `exists` functionality is needed. The `DELETE` method should be implemented if `delete` functionality is needed. Apart from these, all other interfaces methods are provided in terms of `FETCH`, `STORE`, `FETCHSIZE` and `STORESIZE`.

# SEE ALSO

<P5tie>, Tie::StdArray

# AUTHOR

Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)

Source can be located at: <https://github.com/lizmat/Tie-Array> . Comments and Pull Requests are welcome.

# COPYRIGHT AND LICENSE

Copyright 2018, 2019, 2020, 2021 Elizabeth Mattijsen

Re-imagined from Perl as part of the CPAN Butterfly Plan.

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-raku-community-modules-HTTP-Roles.md
[![Actions Status](https://github.com/raku-community-modules/HTTP-Roles/actions/workflows/test.yml/badge.svg)](https://github.com/raku-community-modules/HTTP-Roles/actions)

# NAME

HTTP::Roles - Roles for an HTTP::Server with interchangeable backends

# SYNOPSIS

```
use HTTP::Roles;

my class HTTP::Server::MyWay does HTTP::Server::Role {
    ...
}
my class HTTP::Request::MyWay does HTTP::Request::Role {
    ...
}
my class HTTP::Response::MyWay does HTTP::Response::Role {
    ...
}

```

# DESCRIPTION

HTTP::Roles provides a set of roles to define the functionality of an HTTP server, and handling requests and responses.

# ROLES

## HTTP::Server::Role

All of the methods defined by the `HTTP::Server::Role` take a `Callable` as the argument, which should provide the necessary functionality.

### listen

Calling the `listen` method is telling the server to start up and start accepting connections.

### middleware

The `middleware` method should be called with a `Callable` during server setup: the specified `Callable` is to be executed whenever the reception of the request headers of a request is complete.

### handler

The `handler` method should be called with a `Callable` during server setup: the specified `Callable` is to be executed whenever the reception of the request headers **and** the body of a request is complete.

### after

The `after` method should be called with a `Callable` during server setup: the specified `Callable` is to be executed whenever the response is complete and sent.

## HTTP::Request::Role

The `HTTP::Request::Role` provides some generic attributes for the class that *should* be present in any decent `HTTP::Request` class. These are:

```
has Str $.method;
has Str $.uri;
has Str $.version;
has Buf $.data is rw;
has     %.params;
has     %.headers;

```

### header

A generic `header` method to retrieve headers in a case insensitive way from the `%.headers` attribute.

## HTTP::Response::Role

The `HTTP::Response::Role` provides some generic attributes for the class that *should* be present in any decent `HTTP::Response` class.

```
has Int:D $.status is rw = 200;
has       %.headers is rw;
has       $.connection;
has       %.statuscodes = HTTP::Status.Map;

```

### write

The `write` method is expected to write the given data of the response.

### close

The `close` method is expected to close the connection to the client, taking any optional data to be sent, and a named argument `:force` to forcefully close the connection (which defaults to `False`).

# AUTHOR

Tony O'Dell

# COPYRIGHT AND LICENSE

Copyright 2015 - 2019 Tony O'Dell

Copyright 2020 - 2022 Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## rolepunning.md
role Metamodel::RolePunning

Metaobject that supports *punning* of roles.

```raku
role Perl6::Metamodel::RolePunning {}
```

*Warning*: this role is part of the Rakudo implementation, and is not a part of the language specification.

Implements the ability to create objects from `Role`s without the intermediate need to use a class. Not intended to be used directly (will in fact error if it's `use`d), but via punning of roles, as below. This is also Rakudo specific and not part of the spec.

```raku
role A {
    method b {
      return "punned"
    }
};
my $a = A.new;
say $a.b; # OUTPUT: «punned␤»

```


## dist_zef-vrurg-Cro-RPC-JSON.md
# NAME

`Cro::RPC::JSON` - server side JSON-RPC 2.0 in minutes

# SYNOPSIS

```
use Cro::HTTP::Server;
use Cro::HTTP::Router;
use Cro::RPC::JSON:api<2>;

class JRPC-Actor is export {
    method foo ( Int :$a, Str :$b ) is json-rpc("FOO") {
        return "$b and $a";
    }

    proto method bar (|) is json-rpc { * }

    multi method bar ( Str :$a! ) { "single named Str param" }
    multi method bar ( Int $i, Num $n, Str $s ) { "Int, Num, Str positionals" }
    multi method bar ( *%options ) { [ "slurpy hash:", %options ] }

    method non-json (|) { "I won't be called!" }
}

sub routes is export {
    my $actor = JRPC-Actor.new;
    route {
        # Use an object implementation of API
        post -> "api" {
            json-rpc $actor;
        }
        # Use a code-based implementation of API
        post -> "api2" {
            json-rpc -> Cro::RPC::JSON::Request $jrpc-req {
                { to-user => "a string", num => pi }
            }
        }
    }
}

```

# DESCRIPTION

The initial and primary purpose of this module is to provide a fast path to make your class-based API implementation available to serve [JSON-RPC 2.0](https://www.jsonrpc.org/specification) requests over both HTTP/POST and WebSocket protocols with as little pain as possible. In many cases it is feasible to use the same method to serve both your Raku code and JSON-RPC calls without any special case code paths in the method implementation.

Alongside with supporting class-based API implementation the module also supports code-based scenarios where JSON-RPC requests are handled by a single user-provided code object like a pointy block or a `sub`. This case has two modes of operation: synchronous and asynchronous. These will be discussed later.

## Modes Of Operation

`Cro::RPC::JSON` supports the following modes of operation in mutually exclusive pairs:

* code or object
* HTTP or WebSocket
* synchronous or asynchronous

### Code vs. Object

The [SYNOPSIS](#SYNOPSIS) provides examples for both of the modes. For any relatively complex API object mode would be preferred over code for its higher abstraction level and, correspondingly, for better maintainabilty.

Declaring a class for serving a JSON-RPC requests is as simple as adding `is json-rpc` trait to some of its methods. If we consider `JRPC-Actor` class from [SYNOPSIS](#SYNOPSIS) then calling its method `bar` from a remote client would be done with the following JSON structure:

```
{
    jsonrpc: "2.0",
    id: 314,
    method: "bar",
    params: { a: "string" }
}

```

Which will result in invoking the first `bar` multi-candidate with named parameter `:a<string>`. But if we pass an array together with `params` key: `[42, 3.1415926, "anything"]` – then the second multi-candidate will be called with three positional arguments. This is the basic rule of translation used by `Cro::RPC::JSON`: a top-level JSON object is translated into named parameters; a top-level array represents positional parameters. See more information about handling of method arguments and return values in the [Method Call Convention](#Method Call Convention) section below.

More information about exporting methods for JSON-RPC is provided in `json-rpc` trait section below.

Handling a JSON-RPC request by a code object is considered more low-level approach. Particular format of the code is determined by wether it operates in synchronous or asynchronous mode (see below), general principle is: the code is provided with a [`Cro::RPC::JSON::Request`](JSON/Request.md) object and must produce JSONifiable return value which is then returned to the client. The [SYNOPSIS](#SYNOPSIS) provides the most simple case of a synchronous code object. Any call to JSON-RPC to any method in the example will return:

```
{
    jsonrpc: "2.0",
    id: <user-request-id>,
    result: { "to-user": "a string", num: 3.141592653589793 }
}

```

### HTTP And WebSocket

The difference between these two modes is in the nature of the protocols: where HTTP supports single request/response, WebSocket supports continuous flow of requests/responses and bidirectional communication between client and server. Because handling of an HTTP request is rather easy to understand we're not going to focus much on it. Instead, let's focus in WebSocket specifics of implemeting JSON-RPC by `Cro::RPC::JSON`.

First of all, it has to be mentioned that there is no single specification of how JSON-RPC over WebSocket is to be implemented. `Cro::RPC::JSON` targetting at supporting [rpc-websockets](https://github.com/elpheria/rpc-websockets) implementation for JavaScript.

To handle JSON-RPC request/response protocol a WebSocket stream is considered a bidirectional sequence of JSON objects or arrays of JSON-RPC batch requests/responses. Any server-side notification pushed toward the client must be a JSON object and must not contain `jsonrpc` key.

From the server implementation side of things the above said means that for object mode of operation there is nothing to be changed in method implementations. Everything is handled automatically and makes no difference with HTTP requests. For code objects in synchronous mode there is no change either. But for asynchronous ones it is recommended to use `jrpc-notify` sub to simplify producing of a valid JSON return. The exact meaning of this statement will be clear later.

To get your server support WebSocket transport all is needed is two changes in router code: `get` to be used in place of `post`; and `:web-socket` named argument to be added to call to `json-rpc`:

```
route {
    my $actor = JRPC-Actor.new;
    get -> "api" {
        json-rpc :web-socket, $actor;
    }
}

```

Same applies to a synchronous code mode:

```
route {
    get -> "api2" {
        json-rpc :web-socket, -> Cro::RPC::JSON::Request $jrpc-req {
            { to-user => "a string", num => pi }
        }
    }
}

```

The asynchronous mode wil be considered in the corresponding section later.

It is still possible though for both object and synchronous code mode cases to provide async notifications. See `:async` in sections dedicated to `json-rpc` routine and `json-rpc` trait.

### Synchronous And Asynchronous

Hopefully, by this moment it is clear that in synchronous mode of operation user code receives a request in either raw, as [`Cro::RPC::JSON::Request`](JSON/Request.md) instance, or in a "prepared" form as method arguments. One way or another, a JSONifiable response is produced and that's the end of the cycle for server-side user code.

In asynchronous mode things are pretty much different. First of all, it's not supported for objects; though they still can provide asynchronous notifications using `json-rpc` trait `:async` argument. Second, a code in asynchronous mode receives a [`Supply`](https://docs.raku.org/type/Supply) of incoming requests as an argument and must return a supply emitting [`Cro::RPC::JSON::MethodResponse`](JSON/MethodResponse.md) objects. This is the lowest mode of operation as in this case the code is plugged almost directly into a [`Cro`](https://cro.services) pipeline. See `respond` helper method in [`Cro::RPC::JSON::Request`](JSON/Request.md) which allows to reduce the number of low-level operations needed to emit a resut.

Here is an example of the most simplisic asynchronous code implementation. Note the strict typing used with `$in` parameter. This is how we tell `Cro::RPC::JSON` about our intention to operate asynchronously:

```
route {
    get -> 'api' {
        json-rpc :web-socket, -> Supply:D $in {
            supply {
                whenever $in -> $req {
                    $req.respond: { to-user => "a string", num => pi }
                }
            }
        }
    }
}

```

**Note** that the same asynchronous code can be used for processing an HTTP request too. In this case `:web-socket` argument is not used, `get` turns into `post`, yet otherwise the sample doesn't change. But what remains the same is that `$in` would emit exactly one request object corresponding to the single HTTP `POST`. So, the only case when this approach makes sense if when the same code object is re-used for both WebSocket and HTTP modes.

The above example can be extended to provide additional functionality when operating on a WebSocket:

```
route {
    get -> 'api' {
        json-rpc :web-socket, -> $in, $close {
            supply {
                whenever $in -> $req {
                    $req.respond: { to-user => "a string", num => pi }
                }
                whenever $close -> $req {
                    $close-code = (await $req.body).read-uint16(0);
                    done;
                }
                whenever Supply.interval(1) {
                    jrpc-notify %(
                        :notification<tick-tock>,
                        :params( { :time(now) } )
                    )
                }
            }
        }
    }
}

```

First of all, the absense of `Supply` in front of `$in` is not an error here. Another way to request asynchronous mode of operation is to use declare two parameters. In this case the second one is expected to be a close [`Promise`](https://docs.raku.org/type/Promise) as provided by [`Cro::HTTP::Router::WebSocket`](https://cro.services/docs/reference/cro-http-router-websocket#Receiving_close_messages).

The last `whenever` block apparently produces a notification every second which is then pushed back to the client.

`Cro::RPC::JSON` also provides a hybrid mode of operation where it is possible to provide asynchronous events alongside with a synchronous code. See `:async` argument of `json-rpc` trait and `json-rpc` sub.

# MODULE HELPERS

## `json-rpc`

`json-rpc` is a multi-dispatch `sub` which must be used inside `Cro` `get` or `post` blocks, depending on what transport protocol, HTTP or WebSockets, is to be served. In its most simplistic form `json-rpc` takes a single code object:

```
json-rpc -> $req { ... }

```

Or:

```
json-rpc -> Supply $in { ... }

```

As it was noted above, the type of argument determines wether the code block is to operate in synchronous or asynchronous mode.

Adding a named argument `:web-socket` would tell `json-rpc` to wrap around `Cro`'s `web-socket` subroutine. Same rules about synchronous/asynchronous mode of operation apply:

```
json-rpc :web-socket, -> $req { ... }
json-rpc :web-socket, -> Supply $in { ... }
json-rpc :web-socket, -> $in, $close { ... }

I<C<:web-socket> is also available as C<:ws> or C<:websocket> aliases.>

```

If the first positional argument of `json-rpc` is anything but a code then it is expected to be an object providing methods for JSON-RPC calls. I.e. those marked with `is json-rpc` trait:

```
class JRPC-Actor {
    method authorise(Str:D $name, Str:D $password) is json-rpc { ... }
}
route {
    my $actor = JRPC-Actor.new;
    get -> "api" {
        json-rpc $actor;
    }
}

```

The `$actor` object can also be accompanied with `:web-socket` (`:ws`, `:websocket`) argument.

### `:async`

When a synchronous code is used with `:web-socket` argument it is still possible to emit asynchronous notifications. This is done by passing `:async` named argument to the subroutine which is expected to be a code block which can accept a single argument – WebSocket `$close` [`Promise`](https://docs.raku.org/type/Promise); and which will return a [`Supply`](https://docs.raku.org/type/Supply). The supply is expected to emit JSONifiable notifications to be pushed back to the client code. For example, this is a code from *060-websocket.rakutest* test file:

```
json-rpc :ws, {
    {:foo<sync-bar>}
}, async => -> $close {
    supply {
        my $count = 0;
        my $tap;
        whenever $close { # WebSocket close promise
            $close-code = (await .body).read-uint16(0);
            $tap.close;
        }
        $tap = do whenever Supply.interval(.1) {
            ++$count;
            emit {
                :notification("tick-tock"),
                :params({:$count})
            }
        }
    }
}

```

This little trick allows us to use same synchronous code for serving both HTTP and WebSocket protocols while still allow for asynchronous operations with WebSockets.

This mode of operation is called *hybrid* because it combines both synchronous and asynchronous ones.

**Note** that contrary to the asynchronous code above we don't use `jrpc-notify` to emit a notification. This is because in the case of asynchronous code there is no way for `Cro::RPC::JSON` core to tell the difference between a reponse to a JSON-RPC method call or a notification if they both are hashes, for example, as both are coming from the same supply. That's why one have to wrap them in either [`Cro::RPC::JSON::MethodResponse`](JSON/MethodResponse.md) or [`Cro::RPC::JSON::Notification`](JSON/Notification.md) containers. Besides, when it comes to responding to a method call in the asynchronous model the order of responses is not determined. That's why use of `$req.respond` ensures that the data emitted has the right `id` field set in JSON-RPC response object.

## `jrpc-request`

Returns currently being processed [`Cro::RPC::JSON::Request`](JSON/Request.md) object where applicable and the object is not directly available. Mostly useful for methods of actor class.

## `jrpc-response`

Returns currently being processed [`Cro::RPC::JSON::MethodResponse`](JSON/MethodResponse.md) object where applicable and the object is not directly available. Mostly useful for methods of actor class. Also available as `jrpc-request.jrpc-response`.

## `jrpc-protocol`

A string representing the current transport protocol. Only one of two values is available: *HTTP* or *WebSocket*.

## `jrpc-async`

A [`Bool`](https://docs.raku.org/type/Bool) which is *True* if the code object passed to `json-rpc` subroutine is detected as asynchronous. For object mode of operation it is always *False* for JSON-RPC methods and always *True* for `:async` and `:wsclose` methods (see `json-rpc` trait section below).

**Note** that both `jrpc-protocol` and `jrpc-async` are only available outside of `supply` block of asynchronous code objects. Similarly, `jrpc-request` and `jrpc-response` are not available in asynchronous mode.

## `jrpc-notify`

This subroutine is a conivenience means to reduce the boilerplate of asynchronous code emitting notifications. All it does is wraps it's argument into a [`Cro::RPC::JSON::Notification`](JSON/Notification.md) instance and calls `emit` with the object.

# CREATING AN ACTOR CLASS

Writing an actor class is the most advanced and the most simple way of implementing a complex API. As it was already stated before, the biggest *pro* of this approach is abstracting API implementation from the means of accessing it. In other words, normally it is sufficient to have:

```
use Cro::RPC::JSON:api<2>;
class JRPC-Actor {
    method add(Int:D $a, Int:D $b) is json-rpc { $a + $b }
}

```

The method is then available for both [Raku](https://raku.org) on the server side as:

```
my $sub = $actor.add(13, 42);

```

And for the client code in JavaScript running in a browser:

```
let WebSocket = require('rpc-websockets').Client;
let ws = new WebSocket('ws://localhost:3000');
let sum = await ws.call("add", [13, 42]);

```

Similar JavaScript code can be imagined for any alternative client-side JSON-RPC implementation.

Apparently, all one needs is to use `is json-rpc` trait to mark a method as a JSON-RPC compatible.

**Note** that while we mostly talk about an *actor class* the trait can also be applied to methods in roles. Consuming such role turns a class into a JSON-RPC actor implementation automatically. Inheriting from an actor class also preserves access to the JSON-RPC methods unless they're redefined in a child class without `is json-rpc` trait. *t/005-trait.rakutest* test can be very helpful in providing examples of how things work with Raku OO model.

## Method Call Convention

Methods exported for JSON-RPC are invoked with parameters received from a JSON-RPC request, de-serialized, and flattened. In other words it can be illustrated with:

```
$actor.jrpc-method( |from-json($json-params) );

```

Apparently, this turns any JSON array into positional parameters; and any JSON object into named parameters. Due to the limitations of JSON format, there is no way to pass both named and positionals at the same time.

The only exception from this rule are methods with a single parameter typed with [`Cro::RPC::JSON::Request`](JSON/Request.md). This way a method indicates that it wants to do in-depth analysis of the incoming requests and expects a raw request object.

For developer conivenience the module provides automated serialization of method's return values and de-serialization of arguments. With this feature it's event more easy to write methods universal for both Raku and RPC side of things; and even less boilerplate for any kind of thunk methods.

The most simple case is serialization of return values. It's done in a very straightforward way: a method return is passed to `JSON::Marshal::marshal` sub. The outcome is then sent back to the RPC client.

Somewhat more complicate approach is used for method arguments recived via `params` key of JSON-RPC request. First of all, the module checks if `params` is an array. And if it is then it is considered as a list of positional arguments. This is an unbendable rule.

If `params` is a JSON object and the callee method doesn't have a positional parameter then `params` is considered a set of named arguments. Otherwise it's considered to be the only positional argument of the method.

Before submitting the arguments to the method `Cro::RPC::JSON` first tries to de-serialize them based on method's signature and parameter typing. The algorithm used is basically identical for both positionals and nameds: the module iterates over arguments, matches them to method parameters, and then `JSON::Unmarshal::unmarshal()` with parameter's type. For example:

```
class Product {
    has Int $.SKU;
    has Str $.name;
}
method to-inventory(Product:D $item, Int:D $count) is json-rpc { ... }

```

When `to-inventory` is invoked via this JSON-RPC request:

```
{
    id: 1,
    jsonrpc: "2.0",
    method: "to-inventory",
    params: [
        { SKU: 42, name: "Traveller's Towel" },
        13
    ]
}

```

the first object in `params` array will be de-serialized into a `Product` instance. That's it, we now have method which can be transparently used by both Raky and RPC callers!

If the method is changed to use named parameters:

```
method to-inventory(Product:D :$item, Int:D :$count) is json-rpc {...}

```

Then `params` must be turned into a JSON object like this:

```
{
    item: { SKU: 42, name: "Traveller's Towel" },
    count: 13
}

```

And the outcome will be no different of the positional variant.

Aliasing of named parameters is supported. With this signature:

```
method to-inventory(Product:D :product(:$item), Int:D :$count) is json-rpc {...}

```

We can use the following `params` JSON object:

```
{
    product: { SKU: 42, name: "Traveller's Towel" },
    count: 13
}

```

`Any` type is special cased here. Parameters of `Any` type receive corresponding arguments from the request as-is, no unmarshaling attempted beyond de-stringification of a JSON entity:

```
method foo($x, $y) is json-rpc {...}

params: [true, { a: 1 }]

```

`$x` here will be set to *True*, `$y` – to hash `{ a =` 1 }>.

It is also possible to pass a single positional array argument with `params: [[1, 2, 3]]`.

The unmarshalling will also work correctly for parameterized arrays and hashes. So, if we need to add several objects of the same kind we can do it like this:

```
method to-catalog(Product:D @items) is json-rpc {...}

```

And it will work with:

```
params: [
    { SKU: 42, name: "Traveller's Towel" },
    { SKU: 13, name: "A Happy Amulet" },
    { SKU: 256, name: "Product 100000000" }
]

```

`to-catalog` will receive an array of `Product` instances.

Slurpy parameters are supported as well as captures. The module doesn't attempt unmarshalling of arguments to be consumed by slurpies or captures because there is no way for us to know their types.

The situation is pretty much identical for multi-dispatch methods where to know the eventual candidate to be invoked we nede to know argument types; but we can't know them because we don't know the candidate! For this reason de-serialization is only done based on `proto` method signature:

```
proto method categorize-product(Product:D, |) is json-rpc {*}
multi method categorize-product(Product:D $item, Str:D $category-name) {...}
multi method categorize-product(Product:D $item, Int:D $category-id) {...}

params: [{ SKU: 42, name: "Traveller's Towel" }, "fictional"]
params: [{ SKU: 13, name: "A Happy Amulet" }, 12]

```

Apparently, each of the `params` will dispatch as expected.

## Authorizing Method Calls

`Cro::RPC::JSON` provide means to implement session-based authorization of a method call. It is based on the following two key components:

* Session object, as [documented in a Cro paper](https://cro.services/docs/http-auth-and-sessions), available via `request.auth`. The object must consume [`Cro::RPC::JSON::Auth`](JSON/Auth.md) role and implement `json-rpc-authorize` method
* Authorization object provided with `:auth` modifier of either `json-rpc` or `json-rpc-actor` traits (see below)

The Cro's session object used to authenticate/authorize a HTTP session or a WebSocket connection is expected to provide means of authorizing JSON-RPC method calls too. For this purpose it is expected to consume [`Cro::RPC::JSON::Auth`](JSON/Auth.md) role and implement `json-rpc-authorize` method. Generally speaking, the method is expected to either authorize or prohit an RPC method call based on the available session data. For example, here is an implementation of the session object from a test suite:

```
my class SessionMock does Cro::RPC::JSON::Auth does Cro::HTTP::Auth {
    method json-rpc-authorize($meth-auth) {
        return False if $meth-auth eq 'admin';
        return True if $meth-auth eq 'user' | 'group';
        die "Can't authorize with ", $meth-auth, ": no such privilege";
    }
}

```

This one is really simplistic. It prohibits any activity if it requires *admin* privileges; and only allows anything requiring *user* or *group*. Apparently, the real life requires something more sophisticated, depending on the authorization model of your application.

It is worth mentioning that the auth object associated with a method can be virtually of any type given it's a definite. For example, it can be a [`Junction`](https://docs.raku.org/type/Junction):

```
method self-destroy() is json-rpc(:auth('root' | 'admin')) {...}

```

Because defining the same auth object for every JSON-RPC method could be really boresome, it is possible to define the default one by associating it with actor class:

```
class Foo is json-rpc-actor(:auth<user>) {
    ...
}

```

In this case every JSON-RPC method is considered having *user* auth associated with them unless otherwise specified manually per method declaration.

The authorization takes place whenever a definite auth object can be associated with a method. I.e. it could be an object defined for the method itself; or a default one can be found. Note also that there is no way to bypass authorization in the latter case.

There are some specifics of the authorization process to be considered when class inheritance is involved:

* If a class inherits from one or more actor classes but is not formally declared as a JSON-RPC actor itself then the first defined auth object found on a parent actor class is used.
* The found default auth object overrides any other default specified for classes/roles located further in MRO list. I.e. if classes `Foo` and `Bar` appear in MRO in the order of mentioning; and if `Foo` uses *manager* as the default auth, whereas `Bar` default is *admin*; then any JSON-RPC method from `Bar` with no explicit auth attached will be considered as having it set to *manager*.

## `is json-rpc` Method Trait

In its most simplistic form the trait simply marks a method and exports it for JSON-RPC calls under the same name it is declared in the actor class. But sometimes we need to export it under a different name than the one available for Raku code. In this case we can pass the desired name as trait's first positional argument:

```
method add(Int:D $a, Int:D $b) is json-rpc("sum") { $a + $b }

```

Now we would have to replace *"add"* string in the last JavaScript example with *"sum"*.

The trait also accepts a number of named arguments which are going to be discussed next. They're called *modifiers* as they modify the way the methods are treated by `Cro::RPC::JSON` core. It is important to remember that some modifiers make a method unavailable for JSON-RPC calls:

```
method helper() is json-rpc(:async) { ... }                 # Not available for JSON-RPC

```

Methods marked wit these modifiers become *ad-hoc* methods; the modifiers are correspondingly called *ad-hoc* too. One of the features making ad-hoc methods different from JSON-RPC exports is that they're not overridable in child classes. In other words, if class `Foo` inherits from `Bar` and both define a `:async` ad-hoc named `event-emitter` then both methods will be incorporated into JSON-RPC pipeline. This feature makes `submethod`s ideal candidates for ad-hoc implementation.

Though it's pretty much a bad idea, but if an ad-hoc method is given a name then it becomes a JSON-RPC export too. If for some reason a developer considers this approach then it is better be done by means of a multi-dispatch via applying the trait to method's `proto`:

```
proto method universal(|) is json-rpc("foo", :async) {...}
multi method universal(Promise:D $close) { ... }  # Take care of :async
multi method universal(|c) {...} # Take care of API calls.

```

It is also worth mentioning that applying the trait to a `multi` candidate is equivalent to applying it to its `proto`. While being generally useless withing a class, it allows us to turn a method of parent class into a JSON-RPC accessible one:

```
class Foo {
    has $.value;
    proto method add(|) {*}
    multi method add(::?CLASS:D $b) { $!value += $b.value }
    ...
}
class Bar is Foo {
    multi method add($a, $b) is json-rpc { $!value = $a.value + $b.value }
}

```

So, it is now possible to use the single-argument version of `add` method by a remote client too.

### Ad-Hoc Modifier `:async`

`:async` modifier must be used with methods providing asynchronous events for WebSocket transport. Rules similar to [`json-rpc`](#json-rpc) `:async` named argument apply:

* the method must return a supply emitting either [`Cro::RPC::JSON::Notification`](JSON/Notification.md) instances or JSONifiable objects
* the method may have a single parameter – the WebSocket `$close` [`Promise`](https://docs.raku.org/type/Promise)

  method event-emitter(Promise:D $close?) is json-rpc(:async) {
  supply {
  whenever Supply.interval(1) {
  emit {
  :namespace,
  params => %( time => now )
  }
  }
  with $close {
  whenever $close -> $req {
  my $close-code = (await $req.body).read-uint16(0);
  self.cleanup($close-code);
  }
  }
  }
  }

### Ad-Hoc Modifier `:wsclose`

This is another way to react to WebSocket close event. A method marked with this modifier will be called whenever WebSocket is closed by the client. The only argument passed to the method is the close code as given by the client:

```
method websocket-closed(Int:D $code) is json-rpc(:wsclose) {
    self.cleanup($code);
}

```

### Ad-Hoc Modifier `:last`

`:last` methods are invoked when the incoming [`Supply`](https://docs.raku.org/type/Supply) of WebSocket requests is closed.

The object mode of operations is handled by an asynchronous code similar to this pseudo-code:

```
supply {
    when $in -> $websocket-request {
        ... # Find a method on the object and call it with $websocket-request.params
        LAST {
            ... # Get all :last methods and call them.
        }
    }
}

```

### Ad-Hoc Modifier `:close`

A `:close` method is invoked when the supply block processing WebSocket requests is closed. Done by `CLOSE` phaser on `supply {...}` from the previous section.

### Modifier `:auth(Any:D $auth-obj)`

Non ad-hoc modifier. Defines an authorization object associated with a JSON-RPC exported method. See the section about method call authorization for more details.

## `is json-rpc-actor` Class/Role Trait

It is not normally required to mark a class as a JSON-RPC actor explicitly because applying `json-rpc` trait to a method does it implicitly for us. In practice, this means that the class' `HOW` gets mixed in with `Cro::RPC::JSON::Metamodel::ClassHOW` role. But if we inherit from an actor class the child's `HOW` doesn't get the mixin. `Cro::RPC::JSON` can work with the child as well as with its parent, but sometime we may want the child to be formally declared an actor too. This is when `is json-rpc-actor` comes to help.

### `:auth(Any:D $auth-obj)`

`:auth` modifier defines actor's default authorization object. If a JSON-RPC method doesn't have one associated with it (see `:auth` of `json-rpc` trait) then the default one is used.

# NOTES

## Consuming A Role With JSON-RPC Methods

A role cannot be a JSON-RPC actor. But if a method in it has `json-rpc` trait applied the role becomes a JSON-RPC actor implementation. But a class consuming the role becomes an actor implicitly.

## Cro's `request` Object

One way or another every JSON-RPC request is bound to a HTTP request not matter of the underlying transport. For this reason a number of classes in `Cro::RPC::JSON` provide `request` accessor which contains an instance of [`Cro::HTTP::Request`](https://cro.services/docs/reference/cro-http-request) which started the current JSON-RPC pipeline. Also, Cro's `request` term provides access to the object wherever applicable.

Note that for WebSockets transport the request object is the one about the initial HTTP request which was then upgraded. It can be used, for example, to validate the HTTP session "owning" the current WebSockets connection.

# ERROR HANDLING

`Cro::RPC::JSON` tries to do as much as possible to handle any server-side errors and report them back to the client in a most reasonable way. I.e. if server code dies while processing a method call the client will receive a JSON-RPC object with `error` key with correct error code, error message, and some additional data like server-side exception name and backtrace. But the thing to be remembered: all this related to the synchronous mode of operation only, which also includes actor classes method calls.

The asynchronous mode is totally different here. Due to comparatively low-level approach, code in this mode has to take care of own exceptions. Otherwise if any exception gets leaked it breaks the processing pipeline and results in HTTP 500 response or in WebSocket closing with 1011. This is related to all cases, where a `Supply` is returned by a code, even to `:async` methods.

# SEE ALSO

[`Cro`](https://cro.services), [`Cro::RPC::JSON::Message`](JSON/Message.md), [`Cro::RPC::JSON::Request`](JSON/Request.md), [`Cro::RPC::JSON::MethodResponse`](JSON/MethodResponse.md), [`Cro::RPC::JSON::Notification`](JSON/Notification.md)

# AUTHOR

Vadim Belman [vrurg@cpan.org](mailto:vrurg@cpan.org)

# LICENSE

Artistic License 2.0

See the LICENSE file in this distribution.


## dist_zef-jonathanstowe-FastCGI-NativeCall-PSGI.md
# FastCGI::NativeCall::PSGI

This is a PSGI interface for [FastCGI::NativeCall](https://github.com/jonathanstowe/raku-fastcgi-nativecall)

![Build Status](https://github.com/jonathanstowe/raku-fcgi-psgi/workflows/CI/badge.svg)

## Synopsis

Basic usage:

```
use FastCGI::NativeCall::PSGI;

my $psgi = FastCGI::NativeCall::PSGI.new(path => "/tmp/fastcgi.sock", backlog => 32);

sub dispatch-psgi($env) {
    return [ 200, { Content-Type => 'text/html' }, "Hello world" ];
}

$psgi.run(&dispatch-psgi);

```

Using [Bailador](https://github.com/Bailador/Bailador):

```
use FastCGI::NativeCall::PSGI;
use Bailador;

get "/" => sub {
    "Hello world";
}

my $psgi = FastCGI::NativeCall::PSGI.new(path => "/tmp/fastcgi.sock", backlog => 32);
$psgi.run(get-psgi-app());

```

Using [Crust](https://github.com/tokuhirom/p6-Crust):

```
use FastCGI::NativeCall::PSGI;
use Crust::Builder;

my &app = builder {
    mount "/" , sub (%env) {
        start { 200, [Content-Type => "text/html"], ["Hello world"] };
    }
};

my $psgi = FastCGI::NativeCall::PSGI.new(path => "/tmp/fastcgi.sock", backlog => 32);
$psgi.run(&app);

```

A suitable nginx configuration for these can be found in the <examples> directory.

If you are using Apache httpd with [mod\_fcgid](https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html)
then your script will be executed by the server with its STDIN (file descriptor 0) reopened to
a listening socket that has already been created for you, in this case your constructor will
become:

```
my $psgi = FastCGI::NativeCall::PSGI.new(sock => 0);

```

There is a snippet of Apache configuration in the [examples](examples/apache.conf) directory. You
will almost certainly want to tweak that to your own requirements.

## Description

[FastCGI](https://fastcgi-archives.github.io/) is a protocol that allows
an HTTP server to communicate with a persistent application over a
socket, thus removing the process startup overhead of, say, traditional
CGI applications. It is supported as standard (or through supporting
modules,) by most common HTTP server software (such as Apache, nginx,
lighthttpd and so forth.)

This module builds on
[FastCGI::NativeCall](https://github.com/jonathanstowe/raku-fastcgi-nativecall) to
provide a PSGI/P6GI/P6W interface for web applications.

Despite being single threaded it can be relatively high performance with
appropriate tuning of the server configuration.

## Installation

You will need an HTTP server that supports FastCGI to be able to use this.

Assuming you have a working Rakudo installation then you should be able to insall it with *zef*

```
zef install FastCGI::NativeCall::PSGI

# Or from a local clone

zef install .

```

## Support

I am probably not the right person to be asking about the configuration
of various server software to use FastCGI, you probably want to consult
the manuals in the first place.

Some parts of the support for the full P6GI/P6W spec may be incomplete
but this should be filled out over time.

In testing with [Siege](https://www.joedog.org/siege-home/) some
frameworks performed remarkably worse than others, if you have a concern
about the performance of your application please try to test with another
host server as it may be the framework rather than this module.

Please send suggests/patches etc to [github](https://github.com/jonathanstowe/raku-fcgi-psgi/issues)

## Copyright and Licence

This is free software. Please see the <LICENCE> file for details.

```
Copyright (c) 2015, carlin <cb@viennan.net>
            © 2017 - 2021 Jonathan Stowe

```


## dist_zef-lizmat-P5opendir.md
[![Actions Status](https://github.com/lizmat/P5opendir/actions/workflows/linux.yml/badge.svg)](https://github.com/lizmat/P5opendir/actions) [![Actions Status](https://github.com/lizmat/P5opendir/actions/workflows/macos.yml/badge.svg)](https://github.com/lizmat/P5opendir/actions) [![Actions Status](https://github.com/lizmat/P5opendir/actions/workflows/windows.yml/badge.svg)](https://github.com/lizmat/P5opendir/actions)

# NAME

Raku port of Perl's opendir() and related built-ins

# SYNOPSIS

```
# exports opendir, readdir, telldir, seekdir, rewinddir, closedir
use P5opendir;

opendir(my $dh, $some_dir) || die "can't opendir $some_dir: $!";
my @dots = grep { .starts-with('.') && "$some_dir/$_".IO.f }, readdir($dh);
closedir $dh;

```

# DESCRIPTION

This module tries to mimic the behaviour of Perl's `opendir`, `readdir`, `telldir`, `seekdir`, `rewinddir` and `closedir` built-ins as closely as possible in the Raku Programming Language.

# ORIGINAL PERL 5 DOCUMENTATION

```
opendir DIRHANDLE,EXPR
        Opens a directory named EXPR for processing by "readdir",
        "telldir", "seekdir", "rewinddir", and "closedir". Returns true if
        successful. DIRHANDLE may be an expression whose value can be used
        as an indirect dirhandle, usually the real dirhandle name. If
        DIRHANDLE is an undefined scalar variable (or array or hash
        element), the variable is assigned a reference to a new anonymous
        dirhandle; that is, it's autovivified. DIRHANDLEs have their own
        namespace separate from FILEHANDLEs.

readdir DIRHANDLE
        Returns the next directory entry for a directory opened by
        "opendir". If used in list context, returns all the rest of the
        entries in the directory. If there are no more entries, returns
        the undefined value in scalar context and the empty list in list
        context.

        If you're planning to filetest the return values out of a
        "readdir", you'd better prepend the directory in question.
        Otherwise, because we didn't "chdir" there, it would have been
        testing the wrong file.

            opendir(my $dh, $some_dir) || die "can't opendir $some_dir: $!";
            @dots = grep { /^\./ && -f "$some_dir/$_" } readdir($dh);
            closedir $dh;

        As of Perl 5.12 you can use a bare "readdir" in a "while" loop,
        which will set $_ on every iteration.

            opendir(my $dh, $some_dir) || die;
            while(readdir $dh) {
                print "$some_dir/$_\n";
            }
            closedir $dh;

        To avoid confusing would-be users of your code who are running
        earlier versions of Perl with mysterious failures, put this sort
        of thing at the top of your file to signal that your code will
        work monly on Perls of a recent vintage:

            use 5.012; # so readdir assigns to $_ in a lone while test

telldir DIRHANDLE
        Returns the current position of the "readdir" routines on
        DIRHANDLE. Value may be given to "seekdir" to access a particular
        location in a directory. "telldir" has the same caveats about
        possible directory compaction as the corresponding system library
        routine.

seekdir DIRHANDLE,POS
        Sets the current position for the "readdir" routine on DIRHANDLE.
        POS must be a value returned by "telldir". "seekdir" also has the
        same caveats about possible directory compaction as the
        corresponding system library routine.

closedir DIRHANDLE
        Closes a directory opened by "opendir" and returns the success of
        that system call.

```

# PORTING CAVEATS

The `readdir` function has three modes:

## list mode

By default, `readdir` returns a list with all directory entries found.

```
my @entries = readdir($dh);

```

## scalar context

In scalar context, `readdir` returns one directory entry at a time. Add `Scalar` as the first positional variable to mimic this behaviour:

```
while readdir(Scalar, $dh, :scalar) -> $entry {
    say "found $entry";
}

```

## void context

In void context, `readdir` stores one directory entry at a time in `$_`. Add `Mu` as the first positional variable to mimic this behaviour:

```
.say while readdir(Mu, $dh, :void);

```

## $\_ no longer accessible from caller's scope

In future language versions of Raku, it will become impossible to access the `$_` variable of the caller's scope, because it will not have been marked as a dynamic variable. So please consider changing:

```
readdir;

```

to either:

```
readdir($_);

```

or, using the subroutine as a method syntax, with the prefix `.` shortcut to use that scope's `$_` as the invocant:

```
.&readdir;

```

# AUTHOR

Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)

If you like this module, or what I’m doing more generally, committing to a [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!

Source can be located at: <https://github.com/lizmat/P5opendir> . Comments and Pull Requests are welcome.

# COPYRIGHT AND LICENSE

Copyright 2018, 2019, 2020, 2021, 2023, 2024 Elizabeth Mattijsen

Re-imagined from Perl as part of the CPAN Butterfly Plan.

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-lizmat-Identity-Utils.md
[![Actions Status](https://github.com/lizmat/Identity-Utils/actions/workflows/linux.yml/badge.svg)](https://github.com/lizmat/Identity-Utils/actions) [![Actions Status](https://github.com/lizmat/Identity-Utils/actions/workflows/macos.yml/badge.svg)](https://github.com/lizmat/Identity-Utils/actions) [![Actions Status](https://github.com/lizmat/Identity-Utils/actions/workflows/windows.yml/badge.svg)](https://github.com/lizmat/Identity-Utils/actions)

# NAME

Identity::Utils - Provide utility functions related to distribution identities

# SYNOPSIS

```
use Identity::Utils;

my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>:from<Perl5>";

say short-name($identity);   # Foo::Bar

say ver($identity);          # 0.0.42

say without-ver($identity);  # Foo::Bar:auth<zef:lizmat>:api<2.0>:from<Perl5>

say version($identity);      # v0.0.42

say auth($identity);         # zef:lizmat

say without-auth($identity); # Foo::Bar:ver<0.0.42>:api<2.0>:from<Perl5>

say ecosystem($identity);    # zef

say nick($identity);         # lizmat

say api($identity);          # 2.0

say without-api($identity);  # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:from<Perl5>

say from($identity);         # Perl5

say without-from($identity); # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>

say sanitize($identity);     # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>:from<Perl5>

say build("Foo::Bar", :ver<0.0.42>);  # Foo::Bar:ver<0.0.42>

say is-short-name($identity);   # False
say is-short-name("Foo::Bar");  # True

say is-pinned($identity);   # True
say is-pinned("Foo::Bar");  # False

my $spec        = dependency-specification($identity);
my $compunit    = compunit($identity);
my $meta        = meta($identity, $repo);
my $source-io   = source-io($identity, $repo);
my $source      = source($identity, $repo);
my $bytecode-io = bytecode-io($identity, $repo);
my $bytecode    = bytecode($identity, $repo);

.say for latest-successors(@identities);

use Identity::Utils <short-name auth>;  # only import "short-name" and "auth"

```

# DESCRIPTION

Identity::Utils provides some utility functions for inspecting various aspects of distribution identity strings. They assume any given string is a well-formed identity in the form `name:ver<0.0.1>:auth<eco:nick>` with an optional `api:<1>` field.

A general note with regards to `api`: if it consists of `"0"`, then it is assumed there is **no** api field specified.

# SELECTIVE IMPORTING

```
use Identity::Utils <short-name auth>;  # only import "short-name" and "auth"

```

By default all utility functions are exported. But you can limit this to the functions you actually need by specifying the names in the `use` statement.

To prevent name collisions and/or import any subroutine with a more memorable name, one can use the "original-name:known-as" syntax. A semi-colon in a specified string indicates the name by which the subroutine is known in this distribution, followed by the name with which it will be known in the lexical context in which the `use` command is executed.

```
use Identity::Utils <short-name:name>;  # import "short-name" as "name"

say name("Identity::Utils:auth<zef:lizmat>");  # Identity::Utils

```

# SUBROUTINES

## api

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say api($identity); # 2.0

```

Returns the `api` field of the given identity, or `Nil` if no `api` field could be found.

## auth

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say auth($identity); # zef:lizmat

```

Returns the `auth` field of the given identity, or `Nil` if no `auth` field could be found.

## build

```
my $ver  = "0.0.42";
my $auth = "zef:lizmat";
my $api  = "2.0";
my $from = "Perl5";
say build("Foo::Bar", :$ver, :$auth, :$api, :$from);
  # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>:from<Perl5>

say build("Foo::Bar", :$ver, :nick<lizmat>);
  # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>

```

Builds an identity string from the given short name and optional named arguments:

* ver - the "ver" value to be used
* auth - the "auth" value to be used, overrides "ecosystem" and "nick"
* api - the "api" value to be used
* from - the "from" value to be used, 'Perl6' and 'Raku' will be ignored
* ecosystem - the ecosystem part of "auth", defaults to "zef"
* nick - the nick part of "auth", unless overridden by "auth"

## bytecode

```
my $buf = bytecode($identity);       # default: $*REPO

my $buf = bytecode($identity, ".");  # as if with -I.

```

Returns a `Buf` object with the precompiled bytecode of the given identity and the currently active repository ([`$*REPO`](https://docs.raku.org/language/compilation#$*REPO)).

It is also possible to override the repository (chain) by specifying a second argument, this can be an object of type:

* `Str` - indicate a path for a ::FileSystem repo, just as with -I.
* `IO::Path` - indicate a path for a ::FileSystem repo
* `CompUnit::Repository` - the actual repo to use

Attempts to create the bytecode file if there isn't one yet.

Returns `Nil` if the given identity could not be found, or there is no bytecode file for the short-name of the given identity (probably because it failed to compile).

## bytecode-io

```
my $io = bytecode-io($identity);       # default: $*REPO

my $io = bytecode-io($identity, ".");  # as if with -I.

```

Returns an `IO::Path` object of the precompiled bytecode of the given identity and the currently active repository ([`$*REPO`](https://docs.raku.org/language/compilation#$*REPO)).

It is also possible to override the repository (chain) by specifying a second argument, this can be an object of type:

* `Str` - indicate a path for a ::FileSystem repo, just as with -I.
* `IO::Path` - indicate a path for a ::FileSystem repo
* `CompUnit::Repository` - the actual repo to use

Attempts to create the bytecode file if there isn't one yet.

Returns `Nil` if the given identity could not be found, or there is no bytecode file for the short-name of the given identity (probably because it failed to compile).

## compunit

```
my $compunit = compunit($identity);         # default: $*REPO

my $compunit = compunit($identity, ".");    # as if with -I.

my $compunit = compunit($identity, :need);  # make bytecode

```

Returns a [`Compunit`](https://docs.raku.org/type/CompUnit) object for the given identity and the currently active repository ([`$*REPO`](https://docs.raku.org/language/compilation#$*REPO)).

It is also possible to override the repository (chain) by specifying a second argument, this can be an object of type:

* `Str` - indicate a path for a ::FileSystem repo, just as with -I.
* `IO::Path` - indicate a path for a ::FileSystem repo
* `CompUnit::Repository` - the actual repo to use

A boolean named argument `need` can be specified to indicate that a bytecode file should be created if there is none for this compunit yet.

Returns `Nil` if the given identity could not be found.

## dependency-specification

```
my $spec = dependency-specification($identity);

```

Creates a `CompUnit::DependencySpecification` object for the given identity.

## ecosystem

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say ecosystem($identity); # zef

```

Returns the ecosystem part of the `auth` field of the given identity, or `Nil` if no `auth` field could be found.

## from

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>:from<Perl5>";
say from($identity);  # Perl5

```

Returns the `from` field of the given identity as a `Str`, or `Nil` if no `from` field could be found.

## is-pinned

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say is-pinned($identity);   # True
say is-pinned("Foo::Bar");  # False

```

Returns a boolean indicating whether the given identity is considered to be pinned to a specific release. This implies: having an `auth` and having a version **without** a `+` or a `*` in it.

## is-short-name

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say is-short-name($identity);   # False
say is-short-name("Foo::Bar");  # True

```

Returns a boolean indicating whether the given identity consists of just a `short-name`.

## latest-successors

```
.say for latest-successors(@identies);

```

Returns a sorted `Seq` of identities that have been filtered by the same semantics that are used when installing a module without specifying anything other than a short name of an identity.

For instance, taking:

```
AccountableBagHash:ver<0.0.3>:auth<cpan:ELIZABETH>
AccountableBagHash:ver<0.0.6>:auth<zef:lizmat>

```

would only return `AccountableBagHash:ver<0.0.6>:auth<zef:lizmat>` because it has a higher version number, and the ecosystems are different.

## meta

```
my $meta = meta($identity);       # default: $*REPO

my $meta = meta($identity, ".");  # as if with -I.

```

Returns a hash with the meta information of the given identity and the currently active repository ([`$*REPO`](https://docs.raku.org/language/compilation#$*REPO)) as typically found in the `META6.json` file of a distribution.

It is also possible to override the repository (chain) by specifying a second argument, this can be an object of type:

* `Str` - indicate a path for a ::FileSystem repo, just as with -I.
* `IO::Path` - indicate a path for a ::FileSystem repo
* `CompUnit::Repository` - the actual repo to use

Returns `Nil` if the given identity could not be found.

## nick

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say nick($identity); # lizmat

```

Returns the nickname part of the `auth` field of the given identity, or `Nil` if no `auth` field could be found.

## sanitize

```
my $identity = "Foo::Bar:auth<zef:lizmat>:ver<0.0.42>:api<2.0>";
say sanitize($identity);  # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>

```

Returns a version of the given identity in which any `ver`, `auth` and `api` fields are put in the correct order.

## short-name

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say short-name($identity);  # Foo::Bar

```

Returns the short name part of the given identity, or the identity itself if no `ver`, `auth` or `api` fields could be found.

## source

```
say source($identity);       # default: $*REPO

say source($identity, ".");  # as if with -I.

```

Returns the source-code of the given identity and the currently active repository ([`$*REPO`](https://docs.raku.org/language/compilation#$*REPO)) as typically found in the `lib` directory of a distribution.

It is also possible to override the repository (chain) by specifying a second argument, this can be an object of type:

* `Str` - indicate a path for a ::FileSystem repo, just as with -I.
* `IO::Path` - indicate a path for a ::FileSystem repo
* `CompUnit::Repository` - the actual repo to use

Returns `Nil` if the given identity could not be found, or there is no source-file for the short-name of the given identity.

## source-io

```
my $io = source-io($identity);       # default: $*REPO

my $io = source-io($identity, ".");  # as if with -I.

```

Returns an `IO::Path` object of the source of the given identity and the currently active repository ([`$*REPO`](https://docs.raku.org/language/compilation#$*REPO)) as typically found in the `lib` directory of a distribution.

It is also possible to override the repository (chain) by specifying a second argument, this can be an object of type:

* `Str` - indicate a path for a ::FileSystem repo, just as with -I.
* `IO::Path` - indicate a path for a ::FileSystem repo
* `CompUnit::Repository` - the actual repo to use

Returns `Nil` if the given identity could not be found, or there is no source-file for the short-name of the given identity.

## ver

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say ver($identity);  # 0.0.42

```

Returns the `ver` field of the given identity as a `Str`, or `Nil` if no `ver` field could be found.

## version

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say version($identity);  # v0.0.42

```

Returns the `ver` field of the given identity as a `Version` object, or `Nil` if no `ver` field could be found.

## without-api

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say without-api($identity);  # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>

```

Returns the identity **without** any `api` field of the given identity.

## without-auth

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say without-auth($identity);  # Foo::Bar:ver<0.0.42>:api<2.0>

```

Returns the identity **without** any `auth` field of the given identity.

## without-from

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:from<Perl5>";
say without-from($identity);  # Foo::Bar:ver<0.0.42>:auth<zef:lizmat>

```

Returns the identity **without** any `from` field of the given identity.

## without-ver

```
my $identity = "Foo::Bar:ver<0.0.42>:auth<zef:lizmat>:api<2.0>";
say without-ver($identity);  # Foo::Bar:auth<zef:lizmat>:api<2.0>

```

Returns the identity **without** any `ver` field of the given identity.

# AUTHOR

Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)

Source can be located at: <https://github.com/lizmat/Identity-Utils> . Comments and Pull Requests are welcome.

If you like this module, or what I’m doing more generally, committing to a [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!

# COPYRIGHT AND LICENSE

Copyright 2022, 2024, 2025 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-lizmat-Prompt-Expand.md
[![Actions Status](https://github.com/lizmat/Promp-Expand/actions/workflows/linux.yml/badge.svg)](https://github.com/lizmat/Promp-Expand/actions) [![Actions Status](https://github.com/lizmat/Promp-Expand/actions/workflows/macos.yml/badge.svg)](https://github.com/lizmat/Promp-Expand/actions) [![Actions Status](https://github.com/lizmat/Promp-Expand/actions/workflows/windows.yml/badge.svg)](https://github.com/lizmat/Promp-Expand/actions)

# NAME

Prompt::Expand - provide prompt expansion logic

# SYNOPSIS

```
use Prompt::Expand;

say expand(":time: >");                     # 19:24:11 >

say expand(":yellow,date,reset: >", "NL");  # zon 19 jan 2025 >

```

# DESCRIPTION

The `Prompt::Expand` distribution provides the logic to expand a string (usually intended to be used as a prompt for user input) according to number of escape sequences (`\x`) or placeholder specifications `:text:`. As such it exports an `expand` subroutine that takes such a format, and returns the expanded string.

Placeholders are specified by an initial semi-colon (`:`), followed by one or more identifiers separated by commas, and ended with a final semi-colon.

Expansion currently provided are:

* ANSI color / formatting codes
* strftime escape codes
* emoji escape codes
* other generally useful escapes

Expansions involving date / time values, can be localized by specifying the language to be used, either as a string (e.g. `"NL"`) or as a custom Locale::Dates object.

# EXPANSIONS

## ANSI color codes

Note that **not** all of these are supported everywhere!

| :text: | function |
| --- | --- |
| normal | reset to default |
| bold | switch on bold characters |
| dim | switch on dimmer characters |
| italic | switch on italic characters |
| underline | switch on underlined characters |
| blink | switch on blinking characters |
| inverse | switch on inverted characters |
| hidden | switch on showing spaces instead of characters |
| strikethrough | switch on strikethrough characters |
| unbold | switch off bold characters |
| unitalic | switch off italic characters |
| ununderline | switch off underlined characters |
| uninverse | switch off inverse characters |
| black | switch to black foreground |
| red | switch to red foreground |
| green | switch to green foreground |
| yellow | switch to yellow foreground |
| blue | switch to blue foreground |
| magenta | switch to magenta foreground |
| cyan | switch to cyan foreground |
| white | switch to white foreground |
| default | switch to default foreground |
| BLACK | switch to black background |
| RED | switch to red background |
| GREEN | switch to green background |
| YELLOW | switch to yellow background |
| BLUE | switch to blue background |
| MAGENTA | switch to magenta background |
| CYAN | switch to cyan background |
| WHITE | switch to white background |
| DEFAULT | switch to default background |

## Raku escape sequences

Besides most of the [standard Raku escape sequences](https://docs.raku.org/language/quoting#Interpolating_escape_codes) with an associated `:text:` equivalent, also some other more interactive prompt related `:text` sequences:

| :text: | escape | function |
| --- | --- | --- |
| bell | \a | audible / visible alert |
| bksp | \b | backspace |
| escape | \e | initiate ANSI escape sequence |
| formfeed | \f | form feed (FF) |
| reset | \c | reset to all ANSI defaults |
| lf | \n | line feed (LF, newline, $?NL) |
| cr | \r | Carriage Return (CR) |
| tab | \t | tab |
| bslash | \\ | backslash |
| index |  | $\*INDEX value |
| symbol |  | $\*SYMBOL value |
| language |  | language version |
| release |  | compiler release |
| compiler |  | compiler version |

From [`DateTime::strftime`](https://raku.land/zef:lizmat/DateTime::strftime):

| Code | :text: | Value |
| --- | --- | --- |
| %a | wkdname | abbreviated weekday name |
| %A | weekdayname | full weekday name |
| %b | mnthname | abbreviated month name |
| %B | monthname | full month name |
| %c | datetime | preferred date/time representation |
| %C | century | century number (year div 100) |
| %d | 0day | day of month ("01" .. "31") |
| %D | usadate | short for: %m/%d/%y |
| %e | day | day of month (" 1" .. "31") |
| %f | minute | same as %M |
| %F | isodate | short for: %Y/%m/%d |
| %g | weekYY | YY of this week ("00" .. "99") |
| %G | weekYYYY | full year of this week |
| %h | mnthname | same as %b |
| %H | 0hour | 24-hour hour ("00" .. "23") |
| %I | 0amhour | 12-hour hour ("01" .. "12") |
| %j | yearday | day of the year ("001" .. "366") |
| %k | hour | 24-hour hour (" 1" .. "23") |
| %l | amhour | 12-hour hour (" 1" .. "12") |
| %L | year | same as %Y |
| %m | month | month ("01" .. "12") |
| %M | minute | minute ("00" .. "59") |
| %n | newline | "\n" |
| %p | AMPM | "AM" | "PM" |
| %P | ampm | "am" | "pm" |
| %r | amtime | short for: %I:%M:%S %p |
| %R | HHMM | short for: %H:%M |
| %s | epoch | seconds since epoch (midnight 1970-01-01 UTC) |
| %S | second | second ("00" .. "59") |
| %t | tab | "\t" |
| %T | HHMMSS | short for: %H:%M:%S |
| %u | weekday | weekday (1 .. 7) |
| %U | weekSun | week number (first Sunday) ("00" .. "53") |
| %v | DD-MON-YYYY | short for: %e-%b-%Y |
| %V | weekISO | week number (ISO 8601) ("00" .. "53") |
| %w | 0weekday | weekday (0 .. 6) |
| %W | weekMon | week number (first Monday) ("00" .. "53") |
| %x | date | preferred date representation |
| %X | time | preferred time representation |
| %y | YY | year without century ("00" .. "99") |
| %Y | year | year (yyyy) |
| %z | tzoffset | numeric timezone (±HHMM) |
| %Z | timezone | timezone (no name: %z) |
| %+ | unixdate | short for: %a %b %e %T %Z %G |
| %% | percent | "%" |

From [`Text::Emoji`](https://raku.land/zef:lizmat/Text::Emoji), all of the *1870* conversions are supported.

# AUTHOR

Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)

Source can be located at: <https://github.com/lizmat/Prompt-Expand> . Comments and Pull Requests are welcome.

If you like this module, or what I'm doing more generally, committing to a [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!

# COPYRIGHT AND LICENSE

Copyright 2025 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_cpan-HANENKAMP-AWS-Session.md
# NAME

AWS::Session - Common data useful for accessing and configuring AWS APIs

# SYNOPSIS

```
use AWS::Session;

my $session      = AWS::Session.new(
    profile => 'my-profile',
);

my $profile      = $session.profile;
my $region       = $session.region;
my $data-path    = $session.data-path;
my $config-file  = $session.config-file;
my $ca-bundle    = $session.ca-bundle;
my %api-versions = $session.api-versions;
my $cred-file    = $session.credentials-file;
my $timeout      = $session.metadata-service-timeout;
my $attempts     = $session.metadata-service-num-attempts;

# Read the AWS configuration file
my %config       = $session.get-configuration;
my %profile-conf = $session.get-profile-configuration('default');
my %current-conf = $session.get-current-configuration;

# Read the AWS credentials file
my %cred         = $session.get-credentials;
my %profile-cred = $session.get-profile-credentials('default');
my %current-cred = $session.get-current-credentials;

```

# DESCRIPTION

AWS clients share some common configuration data. This is a configurable module for loading that data.

# ATTRIBUTES

Any attributes provided will override any configuration values found on the system through the environment, configuration, or defaults.

## profile

The configuration files are in INI format. These are broken up into sections. Each section is a profile. This way you can have multiple AWS configurations, each with its own settings and credentials.

## region

This is the AWS region code to use.

## data-path

The botocore system uses data models to figure out how to interact with AWS APIs. This is the path where additional models can be loaded.

## config-file

This is the location of the AWS configuration file.

## ca-bundle

This is the location of the CA bundle to use.

## api-versions

This is a hash of API versions to prefer for each named API.

## credentials-file

This is the location of the credentials file.

## metadata-service-timeout

This is the timeout to use with the metadata service.

## metadata-service-num-attempts

This is the number of attempts to make when using the metadata service.

## session-configuration

This is a map of configuration variable names to AWS::Session::Default objects, which define how to configure them.

# HELPERS

## AWS::Session::Default

This is a basic structural class. All attributes are optional.

### ATTRIBUTES

#### config-file

This is the name of the variable to use when loading the value from the configuration file.

#### env-var

This is an array of names of the environment variable to use for the value.

#### default-value

This is the default value to fallback to.

#### converter

This is a function that will convert values from the configuration file or environment variable to the appropriate object.

# METHODS

## get-configuration

```
method get-configuration($config-file?, :$reload?) returns Hash

```

Returns the full contents of the configuration as a hash of hashes. Normally, this method caches the configuration. Setting the `:reload` flag will force the configuration cache to be ignored.

## get-profile-configuration

```
method get-profile-configuration(Str:D $profile, :$config-file?) returns Hash

```

Returns the named profile configuration.

## get-current-configuration

```
method get-current-configuration() returns Hash

```

Returns the configuration for the current profile.

## get-credentials

```
method get-credentials($credentials-file?) returns Hash

```

Returns the full contents of the credentials file as a hash of hashes. Unlike configuration, the contents of this file is not cached.

## get-profile-credentials

```
method get-profile-credentials(Str:D $profile, :$credentials-file?) returns Hash

```

Returns the named profile credentials.

## get-current-credentials

```
method get-current-credentials() returns Hash

```

Returns the credentials for the current profile.

## get-config-variable

```
method get-config-variable(
    Str $logical-name,
    Bool :$from-instance = True,
    Bool :$from-env = True,
    Bool :$from-config = True,
)

```

Loads the configuration named variable from the current configuration. This is loaded from the configuration file, environment, or whatever according to the default set in `session-configuration`. Returns `Nil` if no such configuration is defined for the given `$logical-name`.

The boolean flags are used to select which methods will be consulted for determining the variable value.

* from-instance When True, the local instance variable will be checked.
* from-env When True, the process environment variables will be searched for the value.
* from-config When True, the shared configuration file will be consulted for the value.

The value will be pulled in the order listed above, with the first value found being the one chosen.


## dist_github-avuserow-Audio-Taglib-Simple.md
# NAME

Audio::Taglib::Simple - Read, write ID3 and other audio metadata with TagLib

# SYNOPSIS

```
my $taglib = Audio::Taglib::Simple.new("awesome.mp3");

# read a tag
say "artist: ", $taglib.artist;

# edit a tag
$taglib.artist = "Awesome Band";
$taglib.save;

# free memory when you're done
$taglib.free;

```

See also examples/taglib.p6

# DESCRIPTION

This module uses NativeCall to provide bindings to TagLib's C API. The C API is
the "simple" API, which only provides commonly used fields that are abstracted
over all file types.

If you are interested in the non-abstract API, check out the
[Audio::TagLib](https://github.com/avuserow/raku-audio-taglib) module.

TagLib supports many audio and tag formats. Audio formats include MP3, MPC,
FLAC, MP4, ASF, AIFF, WAV, TrueAudio, WavPack, Ogg FLAC, Ogg Vorbis, Speex and
Opus file formats. Tag formats include ID3v1, ID3v2, APE, FLAC, Xiph,
iTunes-style MP4 and WMA. See their website for an exhaustive list.

TagLib is nice and fast. The example script runs on a directory of 501 files
(499 are MP3, 2 are non-audio) in around 4 seconds.

# METHODS

## new(Str|IO $file)

Prepares to read the provided file. Dies if the file does not exist or if
TagLib cannot parse it. TagLib attempts to guess the file type here.

## free

Frees the internal data used by TagLib.

## file returns IO

Readonly accessor to the file variable passed in.

## artist() returns Str

Returns the artist of the song.

## album() returns Str

Returns the name of the album associated with the song.

## title() returns Str

Returns the title of the song.

## comment() returns Str

A generic comment field.

## genre() returns Str

A string describing the genre.

## year() returns Int

Returns the year associated with the song as an integer (e.g. 2004) or 0 if not
present.

## track() returns Int

Returns the track number of this song as an integer (e.g. 12) or 0 if not
present.

## save() returns Bool

Call save after assigning to one or more tag attributes (listed above) to write
out the changes.

## length() returns Duration

Returns the length of the file as a Duration. TagLib provides it as an integer.
Not editable.

## bitrate() returns Int

Returns the bit rate of the file as an Int in kb/s. Example: 128. Not editable.

## samplerate() returns Int

Returns the sample rate of the file as an Int in Hz. Example: 44100. Not
editable.

## channels() returns Int

Returns the number of channels present in the file as an Int. Example: 2. Not
editable.

# EXCEPTIONS

## X::InvalidAudioFile

The constructor may raise exceptions if the file does not exist or does not
appear to be audio that TagLib can parse.

### file

The file that is invalid.

### text

The specific error text.

# CAVEATS

* TagLib will start claiming some files are not valid after a
  certain amount of objects are creating them without freeing them.
* TagLib prints some warnings to STDERR directly.
* All fields are read from the metadata, and corrupted files can often have
  incorrect values for length. TagLib does not actually parse the music stream
  to find this out.
* Tags are read at object initialization time. This means that if some other
  process modifies the tags on the music file, you won't see changes unless you
  create a new object.

# REQUIREMENTS

* Rakudo Perl 6 2014.11 or above. Tested primarily on MoarVM.
* NativeCall (included in Rakudo 2015.02 and above)

# TODO

See <TODO>.

# SEE ALSO

[TagLib website](http://taglib.github.io)

[tag\_c.h from the TagLib project](https://github.com/taglib/taglib/blob/master/bindings/c/tag_c.h)


## dist_zef-raku-community-modules-ClassX-StrictConstructor.md
[![Actions Status](https://github.com/raku-community-modules/ClassX-StrictConstructor/actions/workflows/linux.yml/badge.svg)](https://github.com/raku-community-modules/ClassX-StrictConstructor/actions) [![Actions Status](https://github.com/raku-community-modules/ClassX-StrictConstructor/actions/workflows/macos.yml/badge.svg)](https://github.com/raku-community-modules/ClassX-StrictConstructor/actions) [![Actions Status](https://github.com/raku-community-modules/ClassX-StrictConstructor/actions/workflows/windows.yml/badge.svg)](https://github.com/raku-community-modules/ClassX-StrictConstructor/actions)

# NAME

ClassX::StrictConstructor - Make your object constructors blow up on unknown attributes

# SYNOPSIS

```
use ClassX::StrictConstructor;

class Foo does ClassX::StrictConstructor {
    has $.a;
    has %.b;
}

Foo.new(a => 1, b => {bb => 2, bbb => 3});  # ok

Foo.new(a => 1, b => 2, c => 3);            # dies

```

# DESCRIPTION

This is Perl's [MooseX::StrictConstructor](https://metacpan.org/pod/MooseX::StrictConstructor) module ported to Raku as a role.

The test suite is ported as well, except for the parts that don't make sense in Raku anymore.

I had fun writing this. I hope you enjoy using it too.

# AUTHOR

Tadeusz Sośnierz

# COPYRIGHT AND LICENSE

Copyright 2014 - 2019 Tadeusz Sośnierz

Copyright 2024 Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-thundergnat-Text-Center.md
[![Actions Status](https://github.com/thundergnat/Text-Center/actions/workflows/test.yml/badge.svg)](https://github.com/thundergnat/Text-Center/actions)

# NAME

Text::Center - Easy centering of text fields

# SYNOPSIS

```
use Text::Center;

say 'Raku'.&center; # Center in a 79 columns by default, space padded by default
#                                      Raku

say 'Raku'.&center(20); # Center in 20 columns, space padded
#        Raku

say 'Raku'.&center(30, :fill('=')); # Center in 30 columns, equal sign padded
#============ Raku ============

```

# DESCRIPTION

Easily center text in a configurable field width (default 79). Pad with spaces by default but may substitute some other character if desired. Will leave a single space on either side of the text unless the text is too large to fit into the field width. In that case, just returns the text unaltered.

Exports a single subroutine:

`center( $text, $width = 79, :fill(' ') )`

where

```
$text is the text to be centered.

$width (optional) is the field width to center within, default 79

:fill (optional) is the fill character to use, default ' ' (space)

```

# AUTHOR

thundergnat aka Steve Schulze

# COPYRIGHT AND LICENSE

Copyright 2020 thundergnat

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_cpan-JGOFF-Vroom-Reveal.md
# Vroom::Reveal

Vroom::Reveal translates Vroom-format files to Reveal.js format.

# Installation

* Using zef (a module management tool bundled with Rakudo Star):

```
    zef update && zef install ANTLR4

```

## Testing

To run tests:

```
    prove -e perl6

```

## Author

Jeffrey Goff, DrForr on #perl6, <https://github.com/drforr/>

## License

Artistic License 2.0


## dist_cpan-MELEZHIK-Sparrowdo-Prometheus.md
# SYNOPSIS

Simple Sparrowdo installer for Prometheus.

# USAGE

```
$ zef install Sparrowdo::Prometheus
$ sparrowdo --module_run=Prometheus --host=$remote_host

```

# Platforms supported

Any Linux Box with systemd.

# TODO

* Make prometheus configuration file customizable
* Make distribution version customizable

# Author

Alexey Melezhik