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

# NAME

Fortran::Grammar - Grammar to parse FORTRAN source code

# SYNOPSIS

```
use Fortran::Grammar;

```

# DESCRIPTION

**Note**: This module is still in very early development.

# MOTIVATION

Working on large Fortran projects with lots of code that you haven't written yourself and try to understand/debug, I found it to be very handy to have a text filter that scans the source code and automatically wraps `write(*,*) ...` statements around specific codelines, e.g. specific MPI subroutine calls. To get information on this code and fill the `write (*,*) ...` statements with useful information, it has to be parsed.

I initially wrote a Perl script to do this by parsing the source code line-by-line. Parsing became more and more ugly the stranger the code became ( a lot of nested arguments, Fortran-style line continuation with `& \n &`, the code of interest enclosed in `IF`-oneliners, etc...).

When I discovered Raku Grammars, I immediately wanted to implement this :-)

The main goal of this module is not to provide a Fortran syntax-checker (although with a lot of work it could become one...) but to give painless access to the structural components of Fortran statements - e.g. the subroutine name of a subroutine call, its arguments (which may contain function calls or calculations), etc...

# Usage

Use it like any grammar in Raku

```
use Fortran::Grammar; # use the module

# some simple Fortran code
my Str $fortran = q:to/EOT/;
call sub( array(1:2), sin(1.234_prec), & ! Fortran-style linebreak / comment
    & (/ 1.23, 3.45, 6.78 /), "Hello World!" )
EOT

# parse the Fortran code
my $parsed = Fortran::Grammar::FortranBasic.parse: $fortran.chomp,
                rule => "subroutine-call";

say "### input ###";
say $fortran;
say "### parsed ###";
say $parsed;

```

Output:

```
### input ###
call sub( array(1:2), sin(1.234_prec), & ! Fortran-style linebreak / comment
    & (/ 1.23, 3.45, 6.78 /), "Hello World!" )

### parsed ###
｢call sub( array(1:2), sin(1.234_prec), & ! Fortran-style linebreak / comment
    & (/ 1.23, 3.45, 6.78 /), "Hello World!" )｣
 name => ｢sub｣
 arguments => ｢array(1:2), sin(1.234_prec), & ! Fortran-style linebreak / comment
    & (/ 1.23, 3.45, 6.78 /), "Hello World!" ｣
  argument => ｢array(1:2)｣
   value-returning-code => ｢array(1:2)｣
    accessed-variable => ｢array(1:2)｣
     indexed-array => ｢array(1:2)｣
      name => ｢array｣
      array-indices => ｢1:2｣
       array-index => ｢1:2｣
        array-index-region => ｢1:2｣
         value-returning-code => ｢1｣
          in-place => ｢1｣
           atomic => ｢1｣
            number => ｢1｣
             integer => ｢1｣
              digits => ｢1｣
         value-returning-code => ｢2｣
          in-place => ｢2｣
           atomic => ｢2｣
            number => ｢2｣
             integer => ｢2｣
              digits => ｢2｣
  argument => ｢sin(1.234_prec)｣
   value-returning-code => ｢sin(1.234_prec)｣
    function-call => ｢sin(1.234_prec)｣
     name => ｢sin｣
     arguments => ｢1.234_prec｣
      argument => ｢1.234_prec｣
       value-returning-code => ｢1.234_prec｣
        in-place => ｢1.234_prec｣
         atomic => ｢1.234_prec｣
          number => ｢1.234_prec｣
           float => ｢1.234_prec｣
            digits => ｢1｣
            digits => ｢234｣
            precision-spec => ｢_prec｣
             name => ｢prec｣
  argument => ｢(/ 1.23, 3.45, 6.78 /)｣
   value-returning-code => ｢(/ 1.23, 3.45, 6.78 /)｣
    in-place => ｢(/ 1.23, 3.45, 6.78 /)｣
     in-place-array => ｢(/ 1.23, 3.45, 6.78 /)｣
      numbers => ｢1.23, 3.45, 6.78 ｣
       number => ｢1.23｣
        float => ｢1.23｣
         digits => ｢1｣
         digits => ｢23｣
       number => ｢3.45｣
        float => ｢3.45｣
         digits => ｢3｣
         digits => ｢45｣
       number => ｢6.78｣
        float => ｢6.78｣
         digits => ｢6｣
         digits => ｢78｣
  argument => ｢"Hello World!" ｣
   value-returning-code => ｢"Hello World!" ｣
    in-place => ｢"Hello World!" ｣
     atomic => ｢"Hello World!" ｣
      string => ｢"Hello World!" ｣

```

## Special thanks

`smls` on [StackOverflow.com](http://stackoverflow.com/a/42039566/5433146) for an Action object `FALLBACK` method that converts a `Match` object to a JSON-serializable `Hash`.

# AUTHORS

* Yann Büchau
* Raku Community

# COPYRIGHT AND LICENSE

Copyright 2017 Yann Büchau

Copyright 2024 Raku Community

This library is free software; you can redistribute it and/or modify it under the GNU GENERAL PUBLIC LICENSE, Version 3


## dist_cpan-SKAJI-HTTP-Tinyish.md
[![Actions Status](https://github.com/skaji/raku-HTTP-Tinyish/workflows/test/badge.svg)](https://github.com/skaji/raku-HTTP-Tinyish/actions)

# NAME

HTTP::Tinyish - Raku port of HTTP::Tinyish

# SYNOPSIS

Synchronous way:

```
my $http = HTTP::Tinyish.new(agent => "Mozilla/4.0");

my %res = $http.get("http://www.cpan.org/");
warn %res<status>;

$http.post:
  "http://example.com/post",
  headers => { "Content-Type" => "application/x-www-form-urlencoded" },
  content => "foo=bar&baz=quux",
;

$http.mirror:
  "http://www.cpan.org/modules/02packages.details.txt.gz",
  "./02packages.details.txt.gz",
;

```

Asynchronous way:

```
my $http = HTTP::Tinyish.new(:async);

my @url = <
  https://raku.org/
  https://doc.raku.org/
  https://design.raku.org/
>;

my @promise = @url.map: -> $url {
  $http.get($url).then: -> $promise {
    my %res = $promise.result;
    say "Done %res<status> %res<url>";
    %res;
  };
};

my @res = await @promise;

```

# DESCRIPTION

HTTP::Tinyish is a Raku port of <https://github.com/miyagawa/HTTP-Tinyish>. Currently only support curl.

## Str VS Buf

Raku distinguishes Str from Buf. HTTP::Tinyish handles data as Str by default (that is, encode/decode utf-8 if needed by default). If you want to handle data as Buf, please follow the instruction below.

If you want to send Buf content, just specify Buf in content:

```
my $binary-data = "file.bin".IO.slurp(:bin);
$http.post:
  "http://example.com/post",
  content => $binary-data,
;

```

If you want to recieve http content as Buf, then call request/get/post/... method with `bin => True` :

```
my %res = $http.get("http://example.com/image.png", bin => True);
does-ok %res<content>, Buf; # pass

```

And decode `%res<content>` by yourself if you want.

# COPYRIGHT AND LICENSE

Copyright 2015 Shoichi Kaji [skaji@cpan.org](mailto:skaji@cpan.org)

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

Original perl5 HTTP::Tinyish COPYRIGHT and LICENSE:

```
COPYRIGHT
Tatsuhiko Miyagawa, 2015-

LICENSE
This module is licensed under the same terms as Perl itself.

```


## dist_github-retupmoca-Compress-Zlib.md
# Compress::Zlib

This is a (hopefully) nice interface to zlib. It compresses and uncompresses
data using zlib native library.

## Usage

```
use Compress::Zlib;

my $wrapped = Compress::Zlib::Wrap.new($handle); # can be a socket, filehandle, etc
my $wrapped = zwrap($handle); # does the same thing as the above line

$wrapped.send("data");
my $response = $wrapped.get;

gzslurp("file.gz"); # reads in a gzipped file
gzspurt("file.gz", "stuff"); # spits out a gzipped file

```

* Streaming (de)compression

```
use Compress::Zlib;

my $compressor = Compress::Zlib::Stream.new;
loop {
    $socket.write($compressor.deflate($data-chunk));
}
$socket.write($compressor.finish);

my $decompressor = Compress::Zlib::Stream.new;
while !$decompressor.finished {
    my $data-chunk = $decompressor.inflate($socket.read($size));
}

```

* Miscellaneous Functions

```
use Compress::Zlib;

my $compressed = compress($string.encode('utf8'));
my $original = uncompress($compressed).decode('utf8');

```

## Handle Wrapper

* `zwrap($handle, :$gzip, :$zlib, :$deflate --> Compress::Zlib::Wrap)`

Returns a wrapped handle that will read and write data in the compressed format. For example:

```
use Compress::Zlib;

my $file   = "data.txt.gz";
my $handle = try open $file or die "Error reading $file: $!";
my $zwrap  = zwrap($handle, :gzip);

for $zwrap.lines {
    .print
}

$handle.close;

CATCH { default { die "Error reading $file: $_" } }

```

## Slurp/spurt

* `gzslurp($filename, :$bin)`
* `gzspurt($filename, $stuff, :$bin)`

## Stream Class

This currently has very few options. Over time, I will add support for custom
compression levels, gzip/raw deflate streams, etc. If you need a specific feature,
open an issue and I will move it to the top of my priority list.

* `new(:$gzip, :$zlib, :$deflate --> Compress::Zlib::Stream)`

  Creates a new object that can be used for either compressing or decompressing
  (but not both!).

  Defaults to zlib compression.
* `finished( --> Bool)`

  Returns true if the end of the data stream has been reached. In this case,
  you can do nothing more that's useful with this object.
* `bytes-left( --> Int)`

  After an `.inflate` object is `.finished`, this will return the number of bytes in the last
  input buffer that were "past the end" of the compressed data stream.

  Usually used when you're interested in any data that comes after the compressed stream.
* `inflate(Buf $data --> Buf)`

  Decompresses a chunk of data.
* `deflate(Buf $data --> Buf)`

  Compresses a chunk of data.
* `flush( --> Buf)`

  Currently just returns an empty Buf, as inflate and deflate are using Z\_SYNC\_FLUSH.
  To be future-proof, call this any time you need Z\_SYNC\_FLUSH semantics (sending
  a complete request to a server, for example).

  At some point, will cause zlib to flush some of it's internal data structures
  and possibly return more data.
* `finish( --> Buf)`

  Flushes all remaining data from zlib's internal structures, and deallocates
  them.

  Call when you want a Z\_STREAM\_END to happen when compressing, or if you are
  finished with the object.

## Misc Functions

**NOTE: These only handle zlib format data, not gzip or deflate.**

* `compress(Blob $data, Int $level? --> Buf)`

  Compresses binary $data. $level is the optional compression level (0 <= x <= 9); defaults to 6.
* `uncompress(Blob $data --> Buf)`

  Uncompresses previously compressed $data.


## dist_github-tokuhirom-HTTP-MultiPartParser.md
[![Build Status](https://travis-ci.org/tokuhirom/p6-HTTP-MultiPartParser.svg?branch=master)](https://travis-ci.org/tokuhirom/p6-HTTP-MultiPartParser)

# NAME

HTTP::MultiPartParser - low level multipart/form-data parser

# SYNOPSIS

```
use HTTP::MultiPartParser;

$parser = HTTP::MultiPartParser.new(
    boundary  => $boundary,
    on_header => $on_header,
    on_body   => $on_body,
);

while $octets = read_octets_from_body() {
    $parser.parse($octets);
}

$parser.finish;

```

# DESCRIPTION

HTTP::MultiPartParser is low level multipart/form-data parser library.

This library is port of chansen's HTTP::MultiPartParser for Perl5.

# METHODS

## new

```
$parser = HTTP::MultiPartParser.new( );

```

This constructor returns a instance of `HTTP::MultiPartParser`. Valid attributes inculde:

* `boundary` (Mandatory)

  boundary => $value

The unquoted and unescaped *boundary* parameter value from the Content-Type header field. The *boundary* parameter value consist of a restricted set of characters as defined in [RFC 2046](RFC 2046).

```
DIGIT / ALPHA / "'" / "(" / ")" /
"+" / "_" / "," / "-" / "." /
"/" / ":" / "=" / "?"

```

* `on_header` (Mandatory)

  on\_header => sub (Array[Str] $header) { ... }

This callback will be invoked when the header of a part has successfully been received. The callback will only be invoked once for each part.

* `on_body` (Mandatory)

  on\_body => sub (Blob $chunk, Bool $final) { ... }

This callback will be invoked when there is any data available for the body of a part. The callback may be invoked multiple times for each part.

* `on_error`

  on\_error => sub (Blob $message) { ... }

This callback will be invoked anytime an error occurs in the parser. After receiving an error the parser is no longer useful in its current state.

* `max_preamble_size`

  max\_preamble\_size => 32768
* `max_header_size`

  max\_header\_size => 32768

## parse

```
$parser.parse($octets);

```

Parses the given octets.

## finish

```
$parser.finish;

```

Finish the parsing.

# COPYRIGHT AND LICENSE

```
Copyright 2015 Tokuhiro Matsuno <tokuhirom@gmail.com>

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

```

And original perl5's HTTP::MutlipartParser is

```
Copyright 2012-2013 by Christian Hansen.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

```


## dist_cpan-THINCH-Proxy-Watched.md
[![Build Status](https://travis-ci.org/spidererrol/perl6-Proxy-Watched.svg?branch=master)](https://travis-ci.org/spidererrol/perl6-Proxy-Watched)

# NAME

Proxy::Watched - Provides a proxy with a supply that emits whenever the proxy is updated.

# SYNOPSIS

```
use Proxy::Watched;

my $watched := watch-var();
$watched.tap: *.say;
$watched = "Say this!";

Supply.interval(1).tap: -> $i { $watched = $i };
$watched.wait-for(3);

my $monitor;
my $monitored := watch-var($monitor);
$monitor.tap: *.say;
$monitored = "Say this!";

my $typed-monitor;
my $typed-watched := watch-var(Str,$monitor);
$typed-monitor.tap: *.say;
$typed-watched = "Must be a Str";

my $init-monitor;
my $init-watched := watch-var("Initial Value",$monitor);
$init-monitor.tap: *.say;
$init-watched = "Say this!";

```

# DESCRIPTION

Proxy::Watched provides the watch-var method which provides a <Proxy> and also a Monitor.

The Monitor allows you to [tap](Supply/method tap) the value of the <Proxy> to get updated whenever it is updated.

# EXPORTED FUNCTION

This module exports just one function but it has many different forms.

## watch-var()

With no parameters this returns a Proxy which overloads the contained value to provide the method provided by Monitor below. Unlike the separate Monitors this variable does not "does" the role Tappable.

It allows you to call tap, wait-for, or wait-while on the value itself, but if that might conflict with any normal use of the value or you don't want those methods to escape as you pass the values around then use one of the other non-overloaded variants below.

```
my $watched := watch-var();
$watched.tap: *.say;
$watched = "Say this!";

```

## watch-var(:type(Type)!,:init(Value))

This produces a overloaded proxy a above, but with a restricted type (required) and optionally an initial value. Note that :type can be a definite value in which case the type of the value will be used and the value will be used as the default initial value.

```
my $watched := watch-var(:type(Int));
$watched.tap: *.say;
$watched = 45;

my $watched-init := watch-var(:type(Int),:init(0 but "Hello!"));
say $watched-init;

my $lazy := watch-var(:type(7)); # Same as :type(Int),:init(7)

```

## watch-var(:init(Value)!)

This provides an initialised, overloaded proxy without resticting the type.

```
my $watched := watch-var(:init(7));
$watched.tap: *.say;
$watched = "Stringy"; # Valid.

```

## watch-var($monitor,:$init)

With just one parameter you should pass in a variable which will be assigned with the Monitor. The Proxy to be monitored is returned. This means the values are kept as-is rather than being extended with the extra methods. If :$init is specified, sets the initial value of the Proxy to that. No type is enforced on the monitor.

```
my $monitor;
my $monitored := watch-var($monitor);
$monitor.tap: *.say;
$monitored = "Say this!";

```

## watch-var(::Type,$monitor,:$init)

The $monitor parameter is updated with the Monitor, and the returned Proxy is limited to the given Type. If :$init is specified then the Proxy will be set to that value initially.

```
my $typed-monitor;
my $typed-watched := watch-var(Str,$monitor);
$typed-monitor.tap: *.say;
$typed-watched = "Must be a Str";

```

## watch-var(::Type $init,$monitor)

Shorthand for watch-var($init,$monitor,:$init);

# class Monitor

This is the class which gives access to the "Watched" part of the variable.

## method tap

```
method tap(&emit,:&done,:&quit,:&tap --> Tap);

```

See <Supply/tap>. This method is just the tap method on the Supply for the watched variable.

## method wait-for

```
method wait-for($value);
method wait-for(Setty $values);

```

In sink (void) context this method will wait until the watched variable is the same as the value (smartmatch) or one of the values in the set (associative).

In scalar context it will return a promise which will be kept when the above condition is met.

This method may return / keep the promise straight away if the watched variable already meets the condition.

## method wait-while

```
method wait-while($value);
method wait-while(Setty $values);

```

This is basically the opposite of wait-for as it will wait until the watched variable does not match any of the given values.

# AUTHOR

Timothy Hinchcliffe [gitprojects.qm@spidererrol.co.uk](mailto:gitprojects.qm@spidererrol.co.uk)

# COPYRIGHT AND LICENSE

Copyright 2019 Timothy Hinchcliffe

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


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

# NAME

Port of Perl's index() / rindex() built-ins

# SYNOPSIS

```
use P5index; # exports index() / rindex()

say index("foobar", "bar");    # 3
say index("foofoo", "foo", 1); # 3
say index("foofoo", "bar");    # -1

say rindex("foobar", "bar");    # 3
say rindex("foofoo", "foo", 4); # 3
say rindex("foofoo", "bar");    # -1

```

# DESCRIPTION

This module tries to mimic the behaviour of Perl's `index` / `rindex` built-ins as closely as possible in the Raku Programming Language.

# ORIGINAL PERL 5 DOCUMENTATION

```
index STR,SUBSTR,POSITION
index STR,SUBSTR
        The index function searches for one string within another, but
        without the wildcard-like behavior of a full regular-expression
        pattern match. It returns the position of the first occurrence of
        SUBSTR in STR at or after POSITION. If POSITION is omitted, starts
        searching from the beginning of the string. POSITION before the
        beginning of the string or after its end is treated as if it were
        the beginning or the end, respectively. POSITION and the return
        value are based at zero. If the substring is not found, "index"
        returns -1.

rindex STR,SUBSTR,POSITION
rindex STR,SUBSTR
        Works just like index() except that it returns the position of the
        last occurrence of SUBSTR in STR. If POSITION is specified,
        returns the last occurrence beginning at or before that position.

```

# AUTHOR

Elizabeth Mattijsen [liz@wenzperl.nl](mailto:liz@wenzperl.nl)

Source can be located at: <https://github.com/lizmat/P5index> . 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-avuserow-File-ExtendedAttributes.md
[![Actions Status](https://github.com/avuserow/raku-file-extendedattributes/actions/workflows/test.yml/badge.svg)](https://github.com/avuserow/raku-file-extendedattributes/actions)

# NAME

File::ExtendedAttributes - access extended attributes of files

# SYNOPSIS

```
use File::ExtendedAttributes;

say list-attributes($path);

set-attribute($path, "user.test", "hello world");

say get-attribute($path, "user.test"); # as a str
say get-attribute($path, "user.test", :bin); # as a blob

remove-attribute($path, "user.test");

```

# DESCRIPTION

File::ExtendedAttributes is a module to provide low-level access to extended attributes on Linux, sometimes known as `xattr`s. These attributes are used for various metadata stored outside the file itself that can be interpreted by one or more applications.

This feature is well-supported on typical Linux filesystems, but may not be supported in all cases, especially with networked filesystems. Many filesystems generally impose size limits of a single filesystem block (often 1024, 2048, or 4096 bytes), so be frugal with the size of this metadata.

These attributes are conceptually key/value pairs. In Linux, the `key` must begin with a namespace (typically `user`) and a period, such as `"user.test"`. The value is an arbitrary string or blob.

# FUNCTIONS

## list-attributes($path)

Returns a list of attributes defined on the given path.

## get-attribute($path, $key, :$bin)

Returns the value of the attribute if present. This value will be decoded as utf-8, unless the `:bin` parameter is specified.

## set-attribute($path, $key, $value)

Sets the specified attribute to the provided value. `$value` may be a `Str` or a `Blob[uint8]`. If `$value` is a string, it is encoded in utf-8 before being stored.

## remove-attribute($path, $key)

Removes the given attribute. If the specified attribute does not exist, then an error is thrown (errno is `ENODATA`).

# ERRORS

If an error occurs, a Failure is returned. If the error is `ENOTSUP`, then an Exception of `X::File::ExtendedAttributes::Unsupported` is thrown. If the error is `ENODATA`, then `X::File::ExtendedAttributes::NoData` is returned. Otherwise, an ad-hoc exception is thrown.

These are returned as Failures to enable the following approach in one-liners and shorter scripts:

```
my @values = @files.map({get-attribute($_, 'user.my-data') || ''});

```

If you do not check the returned value for truth, an exception will be raised instead.

# SEE ALSO

The commands `getfattr`/`setfattr` and `attr`

The `xattr(7)` manpage

# AUTHOR

Adrian Kreher [avuserow@gmail.com](mailto:avuserow@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2022-2023 Adrian Kreher

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


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

# NAME

Die - Perl like die routine for note + exit

# SYNOPSIS

```
use Die;

die "I don't like you, bruh\n"; # new line at the end == no stack trace
die "something looks broken";   # no new line at end == stack trace
die X::SomeShinyException.new;  # this still works like normal

```

# DESCRIPTION

Raku avoids many magics prevalent in Perl land, among which is automatically omitting the stack trace if the `&die` routine is given a string with a new line at the end.

In Raku, you do the same with `note "foo" and exit 1`... or use this shiny module that adds Perl behaviour to `&die`

# EXPORTS

-head2 &die

```
die "I don't like you, bruh\n"; # new line at the end == no stack trace
die "something looks broken";   # no new line at end == full stack trace
die X::SomeShinyException.new;  # this still works like normal

```

Works just like core `&die` except stack trace will be omitted if you include a newline at the end of the die message.

Note that Perl's `&die` exits with status `255`, while core Raku `&die` and this module's `&die` exit with status `1`.

# AUTHOR

Zoffix Znet

Source can be located at: <https://github.com/raku-community-modules/Die> . Comments and Pull Requests are welcome.

# COPYRIGHT AND LICENSE

Copyright 2017, 2018 Zoffix Znet, 2021- Raku Community

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


## dist_cpan-ANTONOV-Lingua-NumericWordForms.md
# Raku Lingua::NumericWordForms

[![Build Status](https://app.travis-ci.com/antononcube/Raku-Lingua-NumericWordForms.svg?branch=main)](https://app.travis-ci.com/github/antononcube/Raku-Lingua-NumericWordForms)
[![](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)

🇧🇬 🇨🇿 🇬🇧 🇫🇷 🇬🇷 🇯🇵 🇮🇷 🇵🇱 🇷🇺 🇪🇸 🇺🇦

## Introduction

This repository provides a Raku package with functions for the
generation, parsing, and interpretation of numeric word forms in different languages.

The initial versions of the code in this repository can be found in the GitHub repository [AAr1].

The Raku package
[`Lingua::Number`](https://github.com/labster/p6-Lingua-Number), [BL1],
provides word forms (cardinal, ordinal, etc.) generation in many languages.
(But at least for one language the produced forms are incorrect.)

The Raku package
[`Lingua::EN::Numbers`](https://github.com/labster/p6-Lingua-Number), [SS1],
also provides word forms (cardinal, ordinal, etc.) generation in English.

The parsers and interpreters of this package can be seen as complementary
to the functions in [BL1, SS1].

**Remark:** Maybe a more complete version of this package should be merged with
[`Lingua::Number`](https://github.com/labster/p6-Lingua-Number), [BL1].

**Remark:** I can judge the quality of the results only of the languages:
Bulgarian, English, and Russian. The numeric word form interpreters for the rest of the languages
pass testing, but they might have potentially many deficiencies.
(That are easily detected by people who have mastered those languages.)

---

## Installation

Package installations from both sources use [zef installer](https://github.com/ugexe/zef)
(which should be bundled with the "standard" [Rakudo](https://rakudo.org) installation file.)

To install the package from [Raku Modules / PAUSE](https://modules.raku.org)
use the shell command:

```
zef install Lingua::NumericWordForms

```

To install the package from the GitHub repository use the shell command:

```
zef install https://github.com/antononcube/Raku-Lingua-NumericWordForms.git

```

---

## Examples

### Generation

Generation of numeric word forms:

```
use Lingua::NumericWordForms;
say to-numeric-word-form(8093);
say to-numeric-word-form(8093, 'Bulgarian'); # not implemented yet
say to-numeric-word-form(8093, 'Russian');   # not implemented yet

```

Here is a screenshot of the results:

![to-demo](./documents/diagrams/to-numeric-form-demo-Raku-REPL.png)

The first argument of `to-numeric-word-form` can be:

* An integer
* A string that can be parsed into an integer
* A string of numbers separated by ";"
* A list of numbers or strings

Here are examples of the latter two:

```
say to-numeric-word-form('123; 232; 898_934').join('; ');
# one hundred twenty three; two hundred thirty two; eight hundred ninety eight thousand, nine hundred thirty four

say to-numeric-word-form([321, '992', 100_904]).join('; ');
# three hundred twenty one; nine hundred ninety two; one hundred thousand, nine hundred four

```

### Interpretation

Interpretation of numeric word forms:

```
use Lingua::NumericWordForms;
say from-numeric-word-form('one thousand and twenty three');
say from-numeric-word-form('хиляда двадесет и три', 'Bulgarian');
say from-numeric-word-form('tysiąc dwadzieścia trzy', 'Polish');
say from-numeric-word-form('одна тысяча двадцать три', 'Russian');
say from-numeric-word-form('mil veintitrés', 'Spanish');

```

Here is a screenshot of the results:

![from-demo](./documents/diagrams/from-numeric-form-demo-Raku-REPL.png)

The function `from-numeric-word-form` can take as a first argument:

* A string that is a numeric word form
* A string comprised of numeric word forms separated by ";"
* A list or an array of strings

Here are corresponding examples:

```
say from-numeric-word-form('twenty six');
# 26

say from-numeric-word-form(['mil veintitrés', 'dos mil setenta y dos']);
# (1023 2072)

say from-numeric-word-form('two hundred and five; триста четиридесет и две; 二十万六十五'):p;
# (english => 205 bulgarian => 342 japanese => 200065)

```

For more examples see the file
[NumericWordForms-examples.raku](examples/NumericWordForms-parsing-examples.raku).

#### Type of the result

The returned result can be an `Int` object or a `Str` object -- that is controlled with
the adverb `number` (which by default is `True`.) Here is an example:

```
my $res = from-numeric-word-form('one thousand and twenty three');
say $res, ' ', $res.WHAT;
# 1023 (Int)

$res = from-numeric-word-form('one thousand and twenty three', :!number);
say $res, ' ', $res.WHAT;
# 1023 (Str)

```

#### Automatic language detection

Automatic language detection is invoked if the second argument is 'Automatic' or not specified:

```
say from-numeric-word-form('tysiąc dwadzieścia trzy', 'Automatic'):p;
# polish => 1023

say from-numeric-word-form(['tysiąc dwadzieścia trzy', 'twenty three']):p;
# (polish => 1023 english => 23)

```

The adverb `:p` specifies whether the result should be a `Pair` object or a `List` of `Pair` objects
with the detected languages as keys.

### Translation

Translation from one language to another:

```
say translate-numeric-word-form('хиляда двадесет и три', 'Bulgarian' => 'English');

```

(Currently that function translates to English only.)

---

## Roles

This package provides (exports) roles that can be used in grammars or roles in other packages, applications, etc.

For example, see the roles:

```
Lingua::NumericWordForms::Roles::Bulgarian::WordedNumberSpec
Lingua::NumericWordForms::Roles::English::WordedNumberSpec

```

A grammar or role that does the roles above should use the rule:

```
<numeric-word-form>

```

For code examples see the file
[Parsing-examples.raku](./examples/Parsing-examples.raku).

**Remark:** The role `Lingua::NumericWordForms::Roles::WordedNumberSpec` and the corresponding
actions class `Lingua::NumericWordForms::Actions::WordedNumberSpec` are "abstract".
They were introduced in order to have simpler roles and actions code
(and non-duplicated implementations.) Hence, that role and class *should not* be used in
grammars and roles outside of this package.

---

## TODO

The following TODO items are ordered by priority, the most important are on top.

1. Expand parsing beyond trillions
2. Automatic determination of the language
3. Word form generation:

   * English
   * Bulgarian
   * Russian
   * General algorithm
4. Documentation of the general programming approach.

   * What are the main challenges?
   * How the chosen software architecture decisions address them?
   * Concrete implementations walk-through.
   * How to implement / include a new language?
   * How the random numbers test files were made?
   * Profiling, limitations, alternatives.
5. Full, consistent Persian numbers parsing.

   * Currently, Persian number parsing works only for numbers less than 101.
6. General strategy for parsing and interpretation of
   numeric word forms of East Asia languages

   * Those languages use groupings based on 10^4 instead of 10^3.
   * Implementation for Japanese.
7. Implement parsing of ordinal numeric word forms

   * English, French, Greek, and Spanish
   * Bulgarian
   * Czech, Russian, Ukrainian, Polish
   * Japanese
8. Implement parsing of year "shortcut" word forms, like "twenty o three"
9. Implement parsing of numeric word forms for rationals, like "five twelfths"
10. Translation function (from one language to another)

---

# Collaboration notes

* The **main rule** is that the main branch should always be installable and pass all of its tests.
* From the main rule it follows that new features are developed in separate branches or forks.
* The easiest way to collaborate is to create and commit new test files or corrections
  to existing test files.

  * Then I would change the corresponding grammars rules and actions
    in order the package to pass the tests.
* Please use [*Conventional Commits* (CC)](https://www.conventionalcommits.org/en/v1.0.0/).

  * Here is the CC short form stencil (in Raku):
    `<type> ['(' <scope> ')']? ':' <description>`.
  * See the recent commits in this repository for examples.
  * Here are additional examples of CC messages (each line is a separate message):

```
feat:Implemented the parsing of Danish numeric word forms.
docs:Added documentation of right-to-left word forms parsing.
fix(Persian):Corrected tests for numbers larger that 1000.
test:Added new corner cases tests.
test(Ukrainian):Added new tests.

```

---

## Acknowledgements

* Thanks to [spyrettas](https://github.com/spyrettas) for:
  * Riding "shotgun" during the initial implementation of the Greek role, actions, and tests
  * Proofreading and correcting Greek tests and role
* Thanks to [Denis](https://github.com/DenisVCode) for:
  * Proofreading the Czech language unit tests and suggesting corrections.

---

## References

[AAr1] Anton Antonov,
[Raku::DSL::Shared](https://github.com/antononcube/Raku-DSL-Shared).

[BL1] Brent "Labster" Laabs,
[`Lingua::Number`](https://github.com/labster/p6-Lingua-Number).

[SS1] Larry Wall, Steve Schulze,
[Lingua::EN::Numbers](https://github.com/thundergnat/Lingua-EN-Numbers).

---

Anton Antonov
Florida, USA
April-May, 2021


## dist_cpan-SAMGWISE-Music-Engine.md
[![Build Status](https://travis-ci.org/samgwise/p6-Music-Engine.svg?branch=master)](https://travis-ci.org/samgwise/p6-Music-Engine)

# NAME

Music::Engine - Generate music in realtime

# SYNOPSIS

```
use Music::Engine;

```

# DESCRIPTION

Music::Engine is a real-time music generation framework. It provides a convenient way to create adaptive musical systems.

# AUTHOR

```
Sam Gillespie

```

# CONTRIBUTIONS

TO contribute head to the github page: <https://github.com/samgwise/p6-Music-Engine>

# COPYRIGHT AND LICENSE

Copyright 2017

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


## dist_zef-antononcube-Jupyter-Chatbook.md
# Jupyter::Chatbook

[![MacOS](https://github.com/antononcube/Raku-Jupyter-Chatbook/actions/workflows/macos.yml/badge.svg)](https://github.com/antononcube/Raku-Jupyter-Chatbook/actions/workflows/macos.yml)
[![Linux](https://github.com/antononcube/Raku-Jupyter-Chatbook/actions/workflows/linux.yml/badge.svg)](https://github.com/antononcube/Raku-Jupyter-Chatbook/actions/workflows/linux.yml)
[![](https://raku.land/zef:antononcube/Jupyter::Chatbook/badges/version)](https://raku.land/zef:antononcube/Jupyter::Chatbook)

## In brief

This Raku package is a fork of Brian Duggan's
["Jupyter::Kernel"](https://github.com/bduggan/raku-jupyter-kernel), [BDp1].

Here are the top opening statements of the README of "Jupyter::Kernel":

> "Jupyter::Kernel" is a pure Raku implementation of a Raku kernel for Jupyter clients¹.

> Jupyter notebooks provide a web-based (or console-based)
> Read Eval Print Loop (REPL) for running code and serializing input and output.

It is desirable to include the interaction with Large Language Models (LLMs) into
the "typical" REPL systems or workflows. Having LLM-aware and LLM-chat-endowed
notebooks -- **chatbooks** -- can really speed up the:

* Writing and preparation of documents on variety of subjects
* Derivation of useful programming code
* Adoption of programming languages by newcomers

This repository is mostly for experimental work, but it aims to be *always* very
useful for interacting with LLMs via Raku.

**Remark:** The reason to have a separate package -- a fork of
["Jupyter::Kernel"](https://github.com/bduggan/raku-jupyter-kernel) --
is because:

* I plan to introduce 4-6 new package dependencies
* I expect to do a fair amount of UX experimental implementations and refactoring

---

## Installation and setup

From ["Zef ecosystem"](https://raku.land):

```
zef install Jupyter::Chatbook

```

From GitHub:

```
zef install https://github.com/antononcube/Raku-Jupyter-Chatbook.git

```

### macOS specific

If using macOS and [ZMQ](https://zeromq.org) is installed with [homebrew](https://formulae.brew.sh/formula/zeromq),
then it might be necessary to copy the ZMQ library "libzmq.5.dylib" into a directory where `zef` can find it.

For example, see the GitHub Actions workflow file ["macos.yml"](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/.github/workflows/macos.yml).

---

## Jupyter kernel configuration

**Remark:** The instructions in this section follow the instructions in
["Jupyter::Kernel"](https://github.com/bduggan/raku-jupyter-kernel).
The "main" change is using `jupyter-chatbook.raku` instead of `jupyter-kernel.raku`.

### Server Configuration

To generate a configuration directory, and to install a kernel
config file and icons into the default location:

```
jupyter-chatbook.raku --generate-config

```

* Use `--location=XXX` to specify another location.
* Use `--force` to override an existing configuration.

### Logging

By default a log file `jupyter.log` will be written in the
current directory. An option `--logfile=XXX` argument can be
added to the argv argument of the server configuration file
(located at `$(jupyter --data)/kernels/raku/kernel.json`)
to change this.

### Client configuration

The jupyter documentation describes the client configuration.
To start, you can generate files for the notebook or
console clients like this:

```
jupyter notebook --generate-config
jupyter console --generate-config

```

Some suggested configuration changes for the console client:

* set `kernel_is_complete_timeout` to a high number. Otherwise,
  if the kernel takes more than 1 second to respond, then from
  then on, the console client uses internal (non-Raku) heuristics
  to guess when a block of code is complete.
* set `highlighting_style` to `vim`. This avoids having dark blue
  on a black background in the console client.

### Running

Start the web UI with:

```
jupyter-notebook
Then select New -> Raku.

```

You can also use it in the console like this:

```
jupyter-console --kernel=raku

```

Or make a handy shell alias:

```
alias iraku='jupyter-console --kernel=raku'

```

### macOS specific

Consider copying the
[RakuChatbook kernel specifications](./resources)
in the directory "~/Library/Jupyter/kernels/raku". That way IDEs like
[Visual Studio Code](https://code.visualstudio.com)
would find the "RakuChatbook" kernel "quicker" or "more directly."

---

## LLM, DeepL, and WolframAlpha API keys

The default API keys for the chat cells, LLM functions, chat objects, and DeepL cells are taken from
the Operating System (OS) environmental variables
`OPENAI_API_KEY`, `PALM_API_KEY`, `GEMINI_API_KEY`, `MISTRAL_API_KEY`, `DEEPL_AUTH_KEY`, `WOLFRAM_ALPHA_API_KEY`.

The API keys can also be specified using LLM evaluator and configuration options and objects;
see [AA3, AAp2, AAv4].

**Remark:** `PALM_API_KEY` works for both PaLM and Gemini.

---

## Using LLMs in chatbooks

There are four ways to use LLMs in a chatbook:

1. [LLM functions](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-functions-and-chat-objects.ipynb), [AA3, AAp2]
2. [LLM chat objects](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-functions-and-chat-objects.ipynb), [AA4, AAp2]
3. [Code cells with magics](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-cells.ipynb)
   accessing LLMs, like, OpenAI's, [AAp3], or PaLM's, [AAp4]
4. [Notebook-wide chats](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-chats.ipynb)
   that are distributed over multiple code cells with chat-magic specs

The sections below briefly describe each of these ways and have links to notebooks with
more detailed examples.

---

## LLM functions and chat objects

LLM functions as described in [AA3] are best utilized via a certain REPL tool or environment.
Notebooks are the perfect media for LLM functions workflows.
Here is an example of a code cell that defines an LLM function:

```
use LLM::Functions;

my &fcp = llm-function({"What is the population of the country $_ ?"});

```

```
# -> **@args, *%args { #`(Block|5261019071144) ... }

```

Here is another cell that can be evaluated multiple times using different country names:

```
<Niger Gabon>.map({ &fcp($_) })

```

```
# (As of 2021, the estimated population of Niger is approximately 25.9 million. The population of Gabon is approximately 2.22 million as of 2021.)

```

For more examples of LLM functions and LLM chat objects see the notebook
["Chatbook-LLM-functions-and-chat-objects.ipynb"](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-functions-and-chat-objects.ipynb).

**Remark:**
Chatbooks load in their initialization phase the packages
["LLM::Functions"](https://github.com/antononcube/Raku-LLM-Functions), [AAp2], and
["LLM::Prompts"](https://github.com/antononcube/Raku-LLM-Prompts), [AAp10].
"LLM::Prompts" provides a prompt expansion DSL that allows specifications like:

```
#% chat
@Yoda How many students did you train? #Translated|German

```

See the movie ["Jupyter Chatbook multi cell LLM chats teaser (Raku)"](https://www.youtube.com/watch?v=wNpIGUAwZB8), [AAv5].

**Remark:**
Also, in the initialization phase are loaded the packages
["Clipboard"](https://github.com/antononcube/Raku-Clipboard), [AAp5],
["Data::Translators"](https://github.com/antononcube/Raku-Data-Translators), [AAp6],
["Data::TypeSystem"](https://github.com/antononcube/Raku-Data-Translators), [AAp7],
["Text::Plot"](https://github.com/antononcube/Raku-Text-Plot), [AAp8],
and
["Text::SubParsers"](https://github.com/antononcube/Raku-Text-SubParsers), [AAp9],
that can be used to post-process LLM outputs.

---

## LLM cells

The LLMs of OpenAI (ChatGPT, DALL-E) and Google (PaLM, Gemini) can be interacted with using "dedicated" notebook cells.

Here is an example of a code cell with PaLM magic spec:

```
%% gemini, max-tokens=600
Generate a horror story about a little girl lost in the forest and getting possessed.

```

For more examples see the notebook
["Chatbook-LLM-cells.ipynb"](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-cells.ipynb).

---

## Notebook-wide chats

Chatbooks have the ability to maintain LLM conversations over multiple notebook cells.
A chatbook can have more than one LLM conversations.
"Under the hood" each chatbook maintains a database of chat objects.
Chat cells are used to give messages to those chat objects.

For example, here is a chat cell with which a new
["Email writer"](https://developers.generativeai.google/prompts/email-writer)
chat object is made, and that new chat object has the identifier "em12":

```
%% chat-em12, prompt = «Given a topic, write emails in a concise, professional manner»
Write a vacation email.

```

Here is a chat cell in which another message is given to the chat object with identifier "em12":

```
%% chat-em12
Rewrite with manager's name being Jane Doe, and start- and end dates being 8/20 and 9/5.

```

In this chat cell a new chat object is created:

```
%% chat snowman, prompt = ⎡Pretend you are a friendly snowman. Stay in character for every response you give me. Keep your responses short.⎦
Hi!

```

And here is a chat cell that sends another message to the "snowman" chat object:

```
%% chat snowman
Who build you? Where?

```

**Remark:** Specifying a chat object identifier is not required. I.e. only the magic spec `%% chat` can be used.
The "default" chat object ID identifier is "NONE".

**Remark:** The magic keyword "chat" can be separated from the identifier of the chat object with
the symbols "-", "\_", ":", or with any number of (horizontal) white spaces.

For more examples see the notebook
["Chatbook-LLM-chats.ipynb"](https://github.com/antononcube/Raku-Jupyter-Chatbook/blob/master/eg/Chatbook-LLM-chats.ipynb).
For a quick demo see the movie
["Jupyter Chatbook multi cell LLM chats teaser (Raku)"](https://www.youtube.com/watch?v=wNpIGUAwZB8), [AAv5].

Here is a flowchart that summarizes the way chatbooks create and utilize LLM chat objects:

```
flowchart LR
    OpenAI{{OpenAI}}
    Gemini{{Gemini}}
    LLaMA{{LLaMA}}
    LLMFunc[[LLM::Functions]]
    LLMProm[[LLM::Prompts]]
    CODB[(Chat objects)]
    PDB[(Prompts)]
    CCell[/Chat cell/]
    CRCell[/Chat result cell/]
    CIDQ{Chat ID<br/>specified?}
    CIDEQ{Chat ID<br/>exists in DB?}
    RECO[Retrieve existing<br/>chat object]
    COEval[Message<br/>evaluation]
    PromParse[Prompt<br/>DSL spec parsing]
    KPFQ{Known<br/>prompts<br/>found?}
    PromExp[Prompt<br/>expansion]
    CNCO[Create new<br/>chat object]
    CIDNone["Assume chat ID<br/>is 'NONE'"]
    subgraph Chatbook frontend
        CCell
        CRCell
    end
    subgraph Chatbook backend
        CIDQ
        CIDEQ
        CIDNone
        RECO
        CNCO
        CODB
    end
    subgraph Prompt processing
        PDB
        LLMProm
        PromParse
        KPFQ
        PromExp
    end
    subgraph LLM interaction
      COEval
      LLMFunc
      Gemini
      LLaMA
      OpenAI
    end
    CCell --> CIDQ
    CIDQ --> |yes| CIDEQ
    CIDEQ --> |yes| RECO
    RECO --> PromParse
    COEval --> CRCell
    CIDEQ -.- CODB
    CIDEQ --> |no| CNCO
    LLMFunc -.- CNCO -.- CODB
    CNCO --> PromParse --> KPFQ
    KPFQ --> |yes| PromExp
    KPFQ --> |no| COEval
    PromParse -.- LLMProm
    PromExp -.- LLMProm
    PromExp --> COEval
    LLMProm -.- PDB
    CIDQ --> |no| CIDNone
    CIDNone --> CIDEQ
    COEval -.- LLMFunc
    LLMFunc <-.-> OpenAI
    LLMFunc <-.-> Gemini
    LLMFunc <-.-> LLaMA

```

---

## Chat meta cells

Each chatbook session has a Hash of chat objects.
Chatbooks can have chat meta cells that allow the access of the chat object "database" as whole,
or its individual objects.

Here is an example of a chat meta cell (that applies the method `say` to the chat object with ID "snowman"):

```
%% chat snowman meta
say

```

Here is an example of chat meta cell that creates a new chat chat object with the LLM prompt
specified in the cell
(["Guess the word"](https://developers.generativeai.google/prompts/guess-the-word)):

```
%% chat-WordGuesser prompt
We're playing a game. I'm thinking of a word, and I need to get you to guess that word.
But I can't say the word itself.
I'll give you clues, and you'll respond with a guess.
Your guess should be a single word only.

```

Here is another chat object creation cell using a prompt from the package
["LLM::Prompts"](https://raku.land/zef:antononcube/LLM::Prompts), [AAp4]:

```
%% chat yoda1 prompt
@Yoda

```

Here is a table with examples of magic specs for chat meta cells and their interpretation:

| cell magic line | cell content | interpretation |
| --- | --- | --- |
| chat-ew12 meta | say | Give the "print out" of the chat object with ID "ew12" |
| chat-ew12 meta | messages | Give the messages of the chat object with ID "ew12" |
| chat sn22 prompt | You pretend to be a melting snowman. | Create a chat object with ID "sn22" with the prompt in the cell |
| chat meta all | keys | Show the keys of the session chat objects DB |
| chat all | keys | *«same as above»* |

Here is a flowchart that summarizes the chat meta cell processing:

```
flowchart LR
    LLMFunc[[LLM::Functions]]
    CODB[(Chat objects)]
    CCell[/Chat meta cell/]
    CRCell[/Chat meta cell result/]
    CIDQ{Chat ID<br/>specified?}
    KCOMQ{Known<br/>chat object<br/>method?}
    AKWQ{Keyword 'all'<br/>specified?}
    KCODBMQ{Known<br/>chat objects<br/>DB method?}
    CIDEQ{Chat ID<br/>exists in DB?}
    RECO[Retrieve existing<br/>chat object]
    COEval[Chat object<br/>method<br/>invocation]
    CODBEval[Chat objects DB<br/>method<br/>invocation]
    CNCO[Create new<br/>chat object]
    CIDNone["Assume chat ID<br/>is 'NONE'"]
    NoCOM[/Cannot find<br/>chat object<br/>message/]
    CntCmd[/Cannot interpret<br/>command<br/>message/]
    subgraph Chatbook
        CCell
        NoCOM
        CntCmd
        CRCell
    end
    CCell --> CIDQ
    CIDQ --> |yes| CIDEQ
    CIDEQ --> |yes| RECO
    RECO --> KCOMQ
    KCOMQ --> |yes| COEval --> CRCell
    KCOMQ --> |no| CntCmd
    CIDEQ -.- CODB
    CIDEQ --> |no| NoCOM
    LLMFunc -.- CNCO -.- CODB
    CNCO --> COEval
    CIDQ --> |no| AKWQ
    AKWQ --> |yes| KCODBMQ
    KCODBMQ --> |yes| CODBEval
    KCODBMQ --> |no| CntCmd
    CODBEval -.- CODB
    CODBEval --> CRCell
    AKWQ --> |no| CIDNone
    CIDNone --> CIDEQ
    COEval -.- LLMFunc

```

---

## [DeepL](https://www.deepl.com) cells

Chatbooks can have [DeepL](https://www.deepl.com) cells (that use the package
["Lingua::Translation::DeepL"](https://raku.land/zef:antononcube/Lingua::Translation::DeepL),
[AAp15].)
For example:

```
#% deepl, to-lang=German, formality=less, format=text
I told you to get the frames from the other warehouse!

```

```
Ich habe dir gesagt, du sollst die Rahmen aus dem anderen Lager holen!

```

---

## [Mermaid-JS](https://mermaid.js.org) cells

Chatbooks can have [Mermaid-JS](https://mermaid.js.org) cells,
(that use the package ["WWW::MermaidInk"](https://raku.land/zef:antononcube/WWW::MermaidInk), [AAp11].)
For example:

```
#% mermaid, format=svg, background=SlateGray
mindmap
**Chatbook**
    **Direct LLM access**
        OpenAI
            ChatGPT
            DALL-E
        Google
            PaLM
            Gemini
        MistralAI
        LLaMA
    **Notebook wide chats**
        Chat objects
           Named
           Anonymous
        Chat meta cells
        Prompt DSL expansion
    **DeepL**
    **MermaidJS**
        SVG
        PNG
    **Pre-loaded packages**
        LLM::Functions
        LLM::Prompts
        Text::SubParsers
        Data::Translators
        Data::TypeSystem
        Clipboard :ALL
        Text::Plot
        Image::Markup::Utilities
        WWW::LLaMA
        WWW::MermaidInk
        WWW::OpenAI
        WWW::PaLM
        WWW::Gemini
        Lingua::Translation::DeepL

```

---

## Automatic initialization

Both initialization Raku code and LLM personas can be automatically run and loaded respectively.

### Init code

The initialization Raku code can be specified with the OS environmental variable `RAKU_CHATBOOK_INIT_FILE`.

If that variable is not set, the existence of the following files is verified in this order:

1. "~/.config/raku-chatbook/init.raku"
2. "~/.config/init.raku"

If an initialization file is found, an attempt is made to evaluate it. If the evaluation is successful,
then the content of file is used to initialize the Jupyter session. (In addition to the code that is always used for initialization.)

For example, see the file ["./resources/init.raku"](./resources/init.raku).

### LLM personas

The Jupyter session can have pre-loaded LLM personas (i.e. chat objects.)

The LLM personas JSON file can be specified with the OS environmental variable `RAKU_CHATBOOK_LLM_PERSONAS_CONF`.

If that variable is not set, the existence of the following files is verified in this order:

1. "~/.config/raku-chatbook/llm-personas.json"
2. "~/.config/llm-personas.json"

Prompts from ["LLM::Prompts"](https://github.com/antononcube/Raku-LLM-Prompts), [AAp10], can be used in that file.

For example, see the file ["./resources/llm-personas.json"](./resources/llm-personas.json).

The pre-loaded LLM personas (chat objects) can be verified with the magic cell:

```
#% chat meta all
gist

```

---

## Docker

Thanks for @ab5tract there are two Docker files:

1. [Dockerfile](./Dockerfile)
2. [Dockerfile.rakudo-HEAD](./Dockerfile.rakudo-HEAD)

The first is for a "standard" run; the second builds Rakudo.

Create the "core" image [`rchat:1.0`](./Dockerfile.rakudo-HEAD) on Linux with:

```
docker build -f Dockerfile.rakudo-HEAD -t rchat:1.0 .

```

Run a container `chatbook` based on the image `rchat:1.0`:

```
docker run --rm -p 8888:8888 --name chatbook -t rchat:1.0

```

---

## TODO

1. TODO Features
   1. DONE Chat-meta cells (simple)
      * DONE meta
      * DONE all
      * DONE prompt
   2. DONE Gemini cells
   3. DONE LLaMA cells
   4. DONE DeepL cells
   5. DONE Wolfram|Alpha cells
      * Handling cell type: result, simple, or query
   6. TODO Chat-meta cells (via LLM)
   7. TODO DSL ["ProdGDT"](https://github.com/antononcube/Raku-WWW-ProdGDT) cells
   8. DONE Using pre-prepared prompts
      * This requires implementing ["LLM::Prompts"](https://github.com/antononcube/Raku-LLM-Prompts).
        * And populating it with a good number of prompts.
   9. TODO Parse Python style magics
      * See ["JupyterChatbook"](https://github.com/antononcube/Python-JupyterChatbook)
      * See ["Getopt::Long::Grammar"](https://github.com/antononcube/Raku-Getopt-Long-Grammar)
2. TODO Unit tests
   1. DONE PaLM cells
   2. DONE OpenAI cells
   3. DONE MermaidInk cells
   4. TODO DALL-E cells
   5. DONE Chat meta cells
3. TODO Documentation
   * DONE LLM functions and chat objects in chatbooks
   * DONE LLM cells in chatbooks
   * DONE Notebook-wide chats and chat meta cells
   * DONE Introductory video(s)
   * TODO All parameters of OpenAI API in Raku
   * TODO All parameters of PaLM API in Raku
   * TODO More details on prompts

---

## References

### Articles

[AA1] Anton Antonov,
["Literate programming via CLI"](https://rakuforprediction.wordpress.com/2023/03/06/literate-programming-via-cli/),
(2023),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

[AA2] Anton Antonov,
["Generating documents via templates and LLMs"](https://rakuforprediction.wordpress.com/2023/07/11/generating-documents-via-templates-and-llms/),
(2023),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

[AA3] Anton Antonov,
["Workflows with LLM functions"](https://rakuforprediction.wordpress.com/2023/08/01/workflows-with-llm-functions/),
(2023),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

[AA4] Anton Antonov,
["Number guessing games: PaLM vs ChatGPT"](https://rakuforprediction.wordpress.com/2023/08/06/number-guessing-games-palm-vs-chatgpt/),
(2023),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

[AA5] Anton Antonov,
["Chatbook New Magic Cells"](https://rakuforprediction.wordpress.com/2024/05/18/chatbook-new-magic-cells),
(2024),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

[SW1] Stephen Wolfram,
["Introducing Chat Notebooks: Integrating LLMs into the Notebook Paradigm"](https://writings.stephenwolfram.com/2023/06/introducing-chat-notebooks-integrating-llms-into-the-notebook-paradigm/),
(2023),
[writings.stephenwolfram.com](https://writings.stephenwolfram.com).

### Packages

[AAp1] Anton Antonov,
[Jupyter::Chatbook Raku package](https://github.com/antononcube/Raku-Jupyter-Chatbook),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp2] Anton Antonov,
[LLM::Functions Raku package](https://github.com/antononcube/Raku-LLM-Functions),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp3] Anton Antonov,
[WWW::OpenAI Raku package](https://github.com/antononcube/Raku-WWW-OpenAI),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp4] Anton Antonov,
[WWW::PaLM Raku package](https://github.com/antononcube/Raku-WWW-PaLM),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp5] Anton Antonov,
[Clipboard Raku package](https://github.com/antononcube/Raku-Clipboard),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp6] Anton Antonov,
[Data::Translators Raku package](https://github.com/antononcube/Raku-Data-Translators),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp7] Anton Antonov,
[Data::TypeSystem Raku package](https://github.com/antononcube/Raku-Data-TypeSystem),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp8] Anton Antonov,
[Text::Plot Raku package](https://github.com/antononcube/Raku-Text-Plot),
(2022),
[GitHub/antononcube](https://github.com/antononcube).

[AAp9] Anton Antonov,
[Text::SubParsers Raku package](https://github.com/antononcube/Raku-Text-SubParsers),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp10] Anton Antonov,
[LLM::Prompts Raku package](https://github.com/antononcube/Raku-LLM-Prompts),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp11] Anton Antonov,
[WWW::MermaidInk Raku package](https://github.com/antononcube/Raku-WWW-MermaidInk),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp12] Anton Antonov,
[WWW::MistralAI Raku package](https://github.com/antononcube/Raku-WWW-MistralAI),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp13] Anton Antonov,
[WWW::LLaMA Raku package](https://github.com/antononcube/Raku-WWW-LLaMA),
(2024),
[GitHub/antononcube](https://github.com/antononcube).

[AAp14] Anton Antonov,
[WWW::Gemini Raku package](https://github.com/antononcube/Raku-WWW-Gemini),
(2024),
[GitHub/antononcube](https://github.com/antononcube).

[AAp15] Anton Antonov,
[Lingua::Translation::DeepL Raku package](https://github.com/antononcube/Raku-Lingua-Translation-DeepL),
(2022),
[GitHub/antononcube](https://github.com/antononcube).

[AAp16] Anton Antonov,
[WWW::WolframAlpha Raku package](https://github.com/antononcube/Raku-WWW-WolframAlpha),
(2024),
[GitHub/antononcube](https://github.com/antononcube).

[BDp1] Brian Duggan,
[Jupyter:Kernel Raku package](https://github.com/bduggan/raku-jupyter-kernel),
(2017-2023),
[GitHub/bduggan](https://github.com/bduggan).

### Videos

[AAv1] Anton Antonov,
["Raku Literate Programming via command line pipelines"](https://www.youtube.com/watch?v=2UjAdQaKof8),
(2023),
[YouTube/@AAA4Prediction](https://www.youtube.com/@AAA4prediction).

[AAv2] Anton Antonov,
["Racoons playing with pearls and onions"](https://www.youtube.com/watch?v=zlkoNZK8MpU)
(2023),
[YouTube/@AAA4Prediction](https://www.youtube.com/@AAA4prediction).

[AAv3] Anton Antonov,
["Streamlining ChatGPT code generation and narration workflows (Raku)"](https://www.youtube.com/watch?v=mI-oWLz5dYY)
(2023),
[YouTube/@AAA4Prediction](https://www.youtube.com/@AAA4prediction).

[AAv4] Anton Antonov,
["Jupyter Chatbook LLM cells demo (Raku)"](https://www.youtube.com/watch?v=cICgnzYmQZg)
(2023),
[YouTube/@AAA4Prediction](https://www.youtube.com/@AAA4prediction).

[AAv5] Anton Antonov,
["Jupyter Chatbook multi cell LLM chats teaser (Raku)"](https://www.youtube.com/watch?v=wNpIGUAwZB8)
(2023),
[YouTube/@AAA4Prediction](https://www.youtube.com/@AAA4prediction).

---

## *Footnotes*

¹ Jupyter clients are user interfaces to interact with an interpreter kernel like "Jupyter::Chatbook".
Jupyter [Lab | Notebook | Console | QtConsole ] are the jupyter maintained clients.
More info in the [Jupyter documentation site](https://jupyter.org/documentation).


## dist_github-yaml-LibYAML.md
# Perl6 LibYAML

[![Build Status](https://travis-ci.org/yaml/yaml-libyaml-perl6.svg)](https://travis-ci.org/yaml/yaml-libyaml-perl6)

A [Perl 6](https://perl6.org/) interface to
[LibYAML](https://github.com/yaml/libyaml), a [YAML](http://yaml.org/)
1.1 parser and emitter.

# INSTALLATION

You must get and install [libyaml](https://github.com/yaml/libyaml)
first. Then you can install LibYAML with zef:

```
zef install LibYAML

```

## Install from Sources

You can install this LibYAML module from source (optionally also using the
libyaml C code sources) like this:

```
$ git clone https://github.com/yaml/yaml-libyaml-perl6
$ git clone https://github.com/yaml/libyaml
$ (cd libyaml; make -f .makefile)
$ export LD_LIBRARY_PATH=$PWD/libyaml/src/.libs
$ cd perl6-libyaml
$ zef install .

```

# Examples

Note: This is a parser and emitter. The interface will probably change.
If you want to load and dump YAML, take a look at
[YAML.pm6](https://github.com/yaml/yaml-perl6).

```
use LibYAML;

my $parser = LibYAML::Parser.new;

my $emitter = LibYAML::Emitter.new(...options...);

```

Originally LibYAML combined loading and parsing, dumping and emitting. The load
and dump parts have been extracted, modified and moved to yaml/yaml-perl6.

Documentation will be added when we figure out the API we want to use.

# Emitter options

```
:encoding = YAML_ANY_ENCODING
            YAML_UTF8_ENCODING (default)
            YAML_UTF16LE_ENCODING
            YAML_UTF16BE_ENCODING

:sequence-style = YAML_BLOCK_SEQUENCE_STYLE (default)
                  YAML_FLOW_SEQUENCE_STYLE

:mapping-style = YAML_BLOCK_MAPPING_STYLE (default)
                 YAML_FLOW_MAPPING_STYLE

:header or :!header  Output `---` header (default if more than one object output)

:footer or :!footer  Output `...` footer (default false)

:canonical or :!canonical

:indent = 2 .. 9 (default 2)

:width = width of line, default = -1, infinite

:unicode or :!unicode (default True)

:break = YAML_LN_BREAK (default)
         YAML_CR_BREAK
         YAML_CRLN_BREAK

```

# Errors

Throws exceptions `X::LibYAML::Parser-Error` or
`X::LibYAML::Emitter-Error` on error.

# SEE ALSO

[YAMLish](https://github.com/Leont/yamlish) is a pure-perl6 module for
YAML that doesn't rely on an external library like `LibYAML` does.

[YAML.pm6](https://github.com/yaml/yaml-perl6) is a loader and dumper, which
uses LibYAML as a backend.


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

# NAME

Algorithm::Soundex - Soundex algorithms in Raku

# SYNOPSIS

```
use Algorithm::Soundex;

my Algorithm::Soundex $s .= new;
my $soundex               = $s.soundex("Leto");
say "The soundex of Leto is $soundex";

```

# DESCRIPTION

Currently this module contains the American Soundex algorithm, implemented in Raku

If you would like to add other Soundex algorithms, Patches Welcome!

# AUTHOR

Jonathan Leto

# COPYRIGHT AND LICENSE

Copyright 2011 - 2017 Jonathan Leto

Copyright 2024 Raku Community

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


## bag.md
class Bag

Immutable collection of distinct objects with integer weights

```raku
class Bag does Baggy { }
```

A `Bag` is an immutable bag/multiset implementing [`Associative`](/type/Associative), meaning a collection of distinct elements in no particular order that each have an integer weight assigned to them signifying how many copies of that element are considered "in the bag". (For *mutable* bags, see [`BagHash`](/type/BagHash) instead.)

`Bag`s are often used for performing weighted random selections - see [.pick](/routine/pick) and [.roll](/routine/roll).

Objects/values of any type are allowed as bag elements. Within a `Bag`, items that would compare positively with the [===](/routine/===) operator are considered the same element, with the number of how many there are as its weight. But you can also easily get back the expanded list of items (without the order):

```raku
my $breakfast = bag <spam eggs spam spam bacon spam>;

say $breakfast.elems;      # OUTPUT: «3␤»
say $breakfast.keys.sort;  # OUTPUT: «bacon eggs spam␤»

say $breakfast.total;      # OUTPUT: «6␤»
say $breakfast.kxxv.sort;  # OUTPUT: «bacon eggs spam spam spam spam␤»

```

`Bag`s can be treated as object hashes using the [`{ }` postcircumfix operator](/language/operators#postcircumfix_{_}), or the [`< >` postcircumfix operator](/language/operators#postcircumfix_<_>) for literal string keys, which returns the corresponding integer weight for keys that are elements of the bag, and `0` for keys that aren't:

```raku
my $breakfast = bag <spam eggs spam spam bacon spam>;
say $breakfast<bacon>;    # OUTPUT: «1␤»
say $breakfast<spam>;     # OUTPUT: «4␤»
say $breakfast<sausage>;  # OUTPUT: «0␤»
```

# [Creating `Bag` objects](#class_Bag "go to top of document")[§](#Creating_Bag_objects "direct link")

`Bag`s can be composed using the [bag](#sub_bag) subroutine (or `Bag.new`, for which it is a shorthand). Any positional parameters, regardless of their type, become elements of the bag:

```raku
my $n = bag "a" => 0, "b" => 1, "c" => 2, "c" => 2;
say $n.keys.raku;        # OUTPUT: «(:c(2), :b(1), :a(0)).Seq␤»
say $n.keys.map(&WHAT);  # OUTPUT: «((Pair) (Pair) (Pair))␤»
say $n.values.raku;      # OUTPUT: «(2, 1, 1).Seq␤»
```

Alternatively, the `.Bag` coercer (or its functional form, `Bag()`) can be called on an existing object to coerce it to a `Bag`. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a bag with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the bag, and the (cumulative) values become the associated integer weights:

```raku
my $n = ("a" => 0, "b" => 1, "c" => 2, "c" => 2).Bag;
say $n.keys.raku;        # OUTPUT: «("b", "c").Seq␤»
say $n.keys.map(&WHAT);  # OUTPUT: «((Str) (Str))␤»
say $n.values.raku;      # OUTPUT: «(1, 4).Seq␤»
```

Furthermore, you can get a `Bag` by using bag operators (see next section) on objects of other types such as [`List`](/type/List), which will act like they internally call `.Bag` on them before performing the operation. Be aware of the tight precedence of those operators though, which may require you to use parentheses around arguments:

```raku
say (1..5) (+) 4;  # OUTPUT: «Bag(1 2 3 4(2) 5)␤»
```

You can also create a `Bag` with the `.new` method.

```raku
my $breakfast = Bag.new( <spam eggs spam spam bacon spam> );
```

Since 6.d (2019.03 and later) you can also use this syntax for parameterization of the `Bag`, to specify which type of values are acceptable:

```raku
# only allow strings (Str) in the Bag
my $breakfast = Bag[Str].new( <spam eggs spam spam bacon spam> );

# only allow whole numbers (Int) in the Bag
my $breakfast = Bag[Int].new( <spam eggs spam spam bacon spam> );
# Type check failed in binding; expected Int but got Str ("spam")
```

Finally, you can create Bag masquerading as a hash by using the `is` trait:

```raku
my %b is Bag = <a b c>;
say %b<a>;  # OUTPUT: «True␤»
say %b<d>;  # OUTPUT: «False␤»
```

Since 6.d (2019.03 and later), this syntax also allows you to specify the type of values you would like to allow:

```raku
# limit to strings
my %b is Bag[Str] = <a b c>;
say %b<a>;  # OUTPUT: «True␤»
say %b<d>;  # OUTPUT: «False␤»

# limit to whole numbers
my %b is Bag[Int] = <a b c>;
# Type check failed in binding; expected Int but got Str ("a")
```

# [Operators](#class_Bag "go to top of document")[§](#Operators "direct link")

See [Operators with set semantics](/language/setbagmix#Operators_with_set_semantics) for a complete list of "set operators" applicable to, among other types, `Bag`.

Examples:

```raku
my ($a, $b) = bag(2, 2, 4), bag(2, 3, 3, 4);

say $a (<) $b;   # OUTPUT: «False␤»
say $a (<=) $b;  # OUTPUT: «False␤»
say $a (^) $b;   # OUTPUT: «Bag(3(2) 2)␤»
say $a (+) $b;   # OUTPUT: «Bag(2(3) 4(2) 3(2))␤»

# Unicode versions:
say $a ⊂ $b;  # OUTPUT: «False␤»
say $a ⊆ $b;  # OUTPUT: «False␤»
say $a ⊖ $b;  # OUTPUT: «Bag(3(2) 2)␤»
say $a ⊎ $b;  # OUTPUT: «Bag(2(3) 4(2) 3(2))␤»

```

# [Subroutines](#class_Bag "go to top of document")[§](#Subroutines "direct link")

## [sub bag](#class_Bag "go to top of document")[§](#sub_bag "direct link")

```raku
sub bag(*@args --> Bag)
```

Creates a new `Bag` from `@args`.

# [Note on `reverse` and ordering](#class_Bag "go to top of document")[§](#Note_on_reverse_and_ordering "direct link")

This method is inherited from [`Any`](/type/Any#routine_reverse), however, [`Mix`](/type/Mix)es do not have an inherent order and you should not trust it returning a consistent output.

# [See also](#class_Bag "go to top of document")[§](#See_also "direct link")

[Sets, Bags, and Mixes](/language/setbagmix)

# [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")

Type relations for `Bag`

raku-type-graph

Bag
Bag

Any
Any

Bag->Any

Baggy
Baggy

Bag->Baggy

Mu
Mu

Any->Mu

Associative
Associative

QuantHash
QuantHash

QuantHash->Associative

Baggy->QuantHash

[Expand chart above](/assets/typegraphs/Bag.svg)


## callable.md
role Callable

Invocable code object

```raku
role Callable { ... }
```

Role for objects which support calling them. It's used in [`Block`](/type/Block), [`Routine`](/type/Routine), [`Sub`](/type/Sub), [`Method`](/type/Method), [`Submethod`](/type/Submethod) and [`Macro`](/type/Macro) types.

Callables can be stored in `&`-sigiled containers, the default type constraint of such a container is `Callable`.

```raku
my &a = {;}; # Empty block needs a semicolon
my &b = -> {};
my &c = sub () {};
sub foo() {};
my &d = &foo;
```

# [Methods](#role_Callable "go to top of document")[§](#Methods "direct link")

## [method CALL-ME](#role_Callable "go to top of document")[§](#method_CALL-ME "direct link")

```raku
method CALL-ME(Callable:D $self: |arguments)
```

This method is required for the [`( )` postcircumfix operator](/language/operators#postcircumfix_(_)) and the [`.( )` postcircumfix operator](/language/operators#index-entry-.(_)). It's what makes an object actually call-able and needs to be overloaded to let a given object act like a routine. If the object needs to be stored in an `&`-sigiled container, it has to implement Callable.

```raku
class A does Callable {
    submethod CALL-ME(|c){ 'called' }
}
my &a = A;
say a(); # OUTPUT: «called␤»
```

Applying the `Callable` role is not a requirement to make an object callable; if a class simply wants to add subroutine-like semantics in a regular scalar container, the submethod `CALL-ME` can be used for that.

```raku
class A {
    has @.values;
    submethod CALL-ME(Int $x where 0 <= * < @!values.elems) {
        @!values[$x]
    }
}
my $a = A.new: values => [4,5,6,7];
say $a(2); # OUTPUT: «6␤»
```

## [method Capture](#role_Callable "go to top of document")[§](#method_Capture "direct link")

```raku
method Capture()
```

Throws [`X::Cannot::Capture`](/type/X/Cannot/Capture).

# [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")

Type relations for `Callable`

raku-type-graph

Callable
Callable

Mu
Mu

Any
Any

Any->Mu

Code
Code

Code->Callable

Code->Any

ForeignCode
ForeignCode

ForeignCode->Callable

ForeignCode->Any

Block
Block

Block->Code

WhateverCode
WhateverCode

WhateverCode->Code

Routine
Routine

Routine->Block

Sub
Sub

Sub->Routine

Method
Method

Method->Routine

Macro
Macro

Macro->Routine

Submethod
Submethod

Submethod->Routine

Regex
Regex

Regex->Method

[Expand chart above](/assets/typegraphs/Callable.svg)


## dist_zef-jonathanstowe-Sys-Utmp.md
# Sys::Utmp

Raku access to Utmp entries on Unix-like systems.

![Build Status](https://github.com/jonathanstowe/Raku-Sys-Utmp/workflows/CI/badge.svg)

## Description

Sys::Utmp provides access to the Unix user accounting data that may be
described in the utmp(5) manpage. Briefly it records each logged in
user (and some other data regarding the OS lifetime.)

It will prefer to use the getutent() function from the system C library
if it is available but will attempt to provide its own if the OS doesn't
have that. Because the implementation of getutent() differs between
various OS and the C part of this module needs to provide a consistent
interface to Raku it may not represent all the data that is available on
a particular system, similarly there may be documented attributes that
are not captured on some OS.

## Installation

Because the various Unix-like systems have varying implementations of the
utmp facility this uses a small shared library written in C to provide a
consistent interface to the Raku library, this means that you will require
a working C compiler environment to be able to install this module.

It is entirely possible that the assumptions that I have made in the C
part aren't correct for your system and that this will not install or
work properly, if this is the case please see the "Support" section below.

Assuming you have a working Rakudo installation you should be able to
install this with *zef* :

```
# From the source directory

zef install .

# Remote installation

zef install Sys::Utmp

```

## Support

Suggestions/patches are welcomed via github at:

<https://github.com/jonathanstowe/Raku-Sys-Utmp/issues>

I'm not able to test on a wide variety of platforms so any help there would be
appreciated. Also the assumptions in the C library are based on those used
in the XS part of the similarly named Perl 5 module which was written when
I had access to different systems, but time moves on and operating systems
change and some of this could be completely incorrect for some systems where
it previously worked. So if you find that this doesn't compile or work
properly on your system and you can work out why the patches will be most
welcome.

## Licence

This is free software.

Please see the <LICENCE> file in the distribution

© Jonathan Stowe 2015 - 2019


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

# NAME

Text::MiscUtils - A bag of small text processing tricks

# SYNOPSIS

```
# English language utilities
use Text::MiscUtils::English;

say ordinal(11);               # '11th'
say ordinal(23);               # '23rd'

my $n = 2;                     # $n = 1 would give correct singular words
say _s($n, 'geese', 'goose');  # 'geese'
say "fox{_s($n, 'es')}";       # 'foxes'
say 'frog' ~ _s($n);           # 'frogs'

# Text layout utilities
use Text::MiscUtils::Layout;

evenly-spaced(12, '1', '22', '55555');  # '1  22  55555'
text-wrap(6, 'a bc def ghij');          # ['a bc', 'def', 'ghij']

text-columns(5, "12\n34\n", "abc\ndefg\nhi");
# 12     abc
# 34     defg
#        hi

text-columns(4, "12\n34\n", "abc\ndefg\nhi", :sep<|>);
# 12  |abc
# 34  |defg
#     |hi

# Note trailing spaces to pad out to width in text-columns() example output

# Emoji/text presentation variations
use Text::MiscUtils::Emojify;

emojify('⚙');      # '⚙ '
textify('😀');     # '😀'
toneify('🧑', 6);  # '🧑🏿'

```

# DESCRIPTION

Text::MiscUtils is a collection of small text processing routines, none of which are complex enough to merit their own distribution, but in aggregate add up to a bunch of finicky boilerplate no one should have to write yet again.

They get regular use by my other modules/programs, but are by no means perfect. For example, while the utilities in Text::MiscUtils::Layout should work fine with embedded ANSI color codes (ignoring them for purposes of calculating space used) and will approximate Unicode width semantics according to Unicode TR11, they don't currently handle Unicode cursor-moving control characters (such as TAB and CR) or the many non-color ANSI control sequences.

# AUTHOR

Geoffrey Broadwell [gjb@sonic.net](mailto:gjb@sonic.net)

# COPYRIGHT AND LICENSE

Copyright 2016-2024 Geoffrey Broadwell

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


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

# NAME

under-version-control - is an IO::Path under version control?

# SYNOPSIS

```
use under-version-control;

say "current directory is under version control"
  if ".".IO.&under-version-control;

say "file 'foo.bar' is under version control"
  if under-version-control "foo.bar".IO;

```

# DESCRIPTION

under::version::control provides a subroutine that returns True if the argument appears to be under version control.

This is currently defined as it having a sibling ".git" directory, or any of its parents having a ".git" directory.

Intended to be used by CLI scripts before they do massive changes on a file system: being under version control provides a bigger chance of reversibility if something went wrong.

# SEE ALSO

For more fine-grained control on whether a path is under version control, you can also use the [`Git::Files`](https://raku.land/zef:lizmat/Git::Files) distribution for that, or the git related functions in [`path-utils`](https://raku.land/zef:lizmat/path-utils).

# AUTHOR

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

Source can be located at: <https://github.com/lizmat/under-version-control> . 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, 2025 Elizabeth Mattijsen

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


## dist_zef-raku-community-modules-Pod-To-Man.md
# NAME

Pod::To::Man - Render Rakudoc as Roff for man

# SYNOPSIS

From the command line:

```
raku --doc=Man your.rakudoc > your.1

```

From your scripts:

```
use Pod::To::Man;

say Pod::To::Man.pod2man($=pod);

```

# DESCRIPTION

Pod::To::Man is a Raku module that converts a given Rakudoc (pod6) structure to formatted \*roff input, suitable for displaying via the `man(1)` program.

This module also comes with the `rakudoc2man` program, which is a front-end to Pod::To::Man that is a more robust alternative to using Pod::To::Man with Raku's builtin `--doc` renderer.

## Methods

### pod2man

```
method pod2man(
    $pod,
    Str:D  :$program = get-pod-name($pod) // $*PROGRAM.basename,
    Str:D  :$section = $*PROGRAM.basename ~~ / '.' [ 'pm6' | 'rakumod' ] $ / ?? '3rakumod' !! '1',
    Date:D :$date = now.Date,
    Str:D  :$version = $*RAKU.compiler.gist,
    Str:D  :$center = "User Contributed Raku Documentation",
    Bool:D :$urls = True,
)

```

`pod2man` converts a given pod structure to \*roff, returning the string of formatted \*roff.

`:$program` will be the name `pod2man` will use as the name of the manpage. By default, `pod2man` will try to determine the manpage name by looking for the program name specified by any `=head1 NAME` or `=NAME` blocks/text. If it cannot determine the name to use from those, it will default to the value of `$*PROGRAM.basename`.

`:$section` will be the manual section `pod2man` will use. See `man-pages(7)` for more information on the conventions for manpage sections. If `$*PROGRAM.basename` ends in the `'.pm6'` or `'.rakumod'` suffix, the section will be `'3rakumod'`. Otherwise, defaults to `'1'`.

`:$date` is the date to use for the manpage. Defaults to the value of `now.Date`.

`:$version` is the version to use for the manpage heading. Defaults to `$*RAKU.compiler.gist`, which will look something like `'rakudo (20XX.XX)'`.

`:$center` is the text to display in the center of manpage heading. Defaults to `"User Contributed Raku Documentation"`.

`:$urls` is a boolean determining whether to generate URLs for `'L<>'` links. Defaults to `True`.

### render

```
method render($pod)

```

`render` is basically the same thing as `pod2man`, but customization is done through environment variables instead of method parameters. This is because it allows the render to be customized when using the `--doc` option in Raku. If you're using Pod::To::Man in your code directly, you should just use `pod2man`.

The following environment variables are supported, each corresponding to their respective `pod2man` parameter.

* `RAKUDOC2MAN_PROGRAM`
* `RAKUDOC2MAN_SECTION`
* `RAKUDOC2MAN_DATE`
* `RAKUDOC2MAN_VERSION`
* `RAKUDOC2MAN_CENTER`
* `RAKUDOC2MAN_URLS`

Most of them accept the same values as their `pod2man` counterparts. `RAKUDOC2MAN_DATE` must be given a date string following the `YYYY-MM-DD` format. `RAKUDOC2MAN_URLS` must be given a number, with `0` equating to `False` and any non-zero value being `True`.

### pod2roff

```
method pod2roff($pod)

```

This method exists only for compatibility reasons. You should use `pod2man` instead.

# BUGS

Don't be ridiculous...

Report bugs on this project's GitHub page, <https://github.com/1-1sam-org/Pod-To-Man>.

# AUTHORS

* Mike Clarke [clarkema@clarkema.org](mailto:clarkema@clarkema.org)
* Vadim Belman [vrurg@lflat.org](mailto:vrurg@lflat.org)
* Samuel Young [samyoung12788@gmail.com](mailto:samyoung12788@gmail.com)

# COPYRIGHT AND LICENSE

* Copyright © 2019-2022 Mike Clarke
* Copyright © 2022, 2025 Raku Community
* Copyright © 2025 Samuel Young

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

# SEE ALSO

man(1), roff(1), man(7), man-pages(7)


## dist_cpan-RBT-DBIish-Pool.md
# DBIish::Pool - Database connection pooling for DBIish

## SYNOPSIS

```
my %connection-parameters = database => 'foo', user => 'bar', password => secret();
my $pool = DBIish.new(driver => 'Pg', initial-size => 1, max-connections => 10, min-spare-connections => 1,
                     max-idle-duration => Duration.new(60), |%connection-parameters);

my $dbh = $pool.get-connection()

$dbh.do({SELECT 1});

$dbh.dispose;

```

## DESCRIPTION

This module is useful for apps supporting multiple parallel users which arrive at an inconsistent rate, such as a
web application. In addition to connection reuse it allow configuring a maximum number of simultaneous connections to
ensure the database does not go over capacity.

Database connection reuse improves performance significantly for very simple transactions, or
long distance networks using SSL encrypted connections. 300% has been seen within the same network
for web requests, where each request was establishing a new connection.

To use, create a pool, then take a connection from that pool. The connection is returned to the pool when
dispose is called. Calling dispose is important as otherwise you may exhaust the pool due to garbage collection
being unpredictable.

See your database driver for a description of the connection parameters allowed. These are the same as the
C<DBIish.connect> call.

```
my $pool = DBHish::Pool.new(driver => 'Pg', max-connections => 20, max-idle-duration => Duration.new(60),
    min-spare-connections => 3,  initial-size => 5, |%dbiish-connection-parameters);

sub do-db-work() {
  my $dbh = $pool.get-connection();

  my $sth = $dbh.prepare(q{ SELECT session_state FROM sessions WHERE session_id = ? });

  $sth.execute($session-id);
  my $ret = $sth.allrows();
  $dbh.dispose

  return $ret;
}

```

### `new`

* `min-spare-connections`

  The number of idle connections to keep around. These are ready for immediate use. Busy multi-threaded workloads
  will want to raise this above 1 as there is a short time between when a connection is disposed and when it
  will be ready for use again.
* `initial-size`

  The number of connections to create when the pool is established. This may be kept equal to `min-spare-connections`
  unless your app requires a very fast initial response time and is regularly restarted during peak periods.
* `max-idle-duration`

  Connections which have not been used in this time period will be slowly closed, unless required to meet the
  `min-spare-connections`.
* `max-connections`

  Maximum number of database connections, including those currently being scrubbed of session state for reuse.
  Overall performance is often better if the database has a consistent load and spikes are smoothed out.
* `|%dbiish-connection-parameters` are whatever `DBIish` allows. For a pool for a PostgreSQL driver might be established
  like this:

  ```
  my $pool = DBIish::Pool.new(driver => 'Pg', dbname => 'dbtest', user => 'postgres', port => 5432, max-connections => 20);

  ```

### `get-connection`

Returns a connection from the pool, establishing a new connection if necessary, when one becomes available. The
connection is checked for connectivity prior to returning it to the client.

Once `max-connections` is reached, this routine will not return a connection until one becomes available. Ensure you
call `dispose` after finished using the connection to shorten this timeframe as garbage collection is not predictable.

If preferred, you may obtain a connection asynchronously.

```
my $dbh = await $pool.get-connection(:async);

```

### Pool Statistics

A small Hash with pool connection statistics is available. This can be useful for automated monitoring purposes.

my %stats = $pool.stats();

Statistics fields include:

* inuse ➡ Number of connections currently in use.
* idle ➡ Number available for immediate use.
* starting ➡ Number starting up.
* scrub ➡ Numbers recently disposed, currently being scrubbed.
* total ➡ Total of the `inuse`, `idle`, `starting`, and `scrub` counters. Due to short race conditions, this may not add up at times.
* waiting ➡ Number of unfilled `connect` calls.


## dist_zef-ian-nai-lemmatize.md
# Raku Lemmatize

A Raku module to lemmatize strings and lists, with support for 24 languages.

## Installation

Install using zef:

```
zef install lemmatize

```

Or simply download the GitHub repo.

## Usage

The package uses csv files containing predefined lemmas in a two column format, with the lemma on the left and its derivatives on the right. Any similarly formatted .csv can be used to run the code, allowing for easy use of custom lemma lists
and additional languages.

The following four subroutines can be called:

To construct your hash table of lemma pairs; this must be done before lemmatizing:

```
construct_hash('resources/en.csv');
# or substitute your own filename in place of 'lemmas.csv'

```

To lemmatize a string (which also converts every character in the string to lowercase):

```
lemmatize_string($your_string);

```

To lemmatize an array of words (which also converts every string in the list to lowercase):

```
lemmatize_array(@your_array);

```

To convert a string to an array of its component words:

```
words_to_array($your_string);

```

## Supported Languages and Their Codes

The following languages are included in the package, and their lemma pairs are stored in csv files titled with their language codes (e.g., 'ast.csv').

* Asturian - ast
* Bulgarian - bg
* Catalan - ca
* Czech - cs
* English - en
* Estonian - et
* French - fr
* Galician - gl
* German - de
* Hungarian - hu
* Irish - ga
* Manx Gaelic - gv
* Italian - it
* Persian/Farsi - fa
* Portuguese - pt
* Romanian - ro
* Russian - ru
* Scottish Gaelic - gd
* Slovak - sk
* Slovene - sl
* Spanish - es
* Swedish - sv
* Ukrainian - uk
* Welsh - cy

## Lemma List and Formatting

### Source

The list of English lemmas included here was sourced from [this GitHub repo](https://github.com/skywind3000/lemma.en) by [Lin Wei.](https://github.com/skywind3000), and the other languages were sourced from [this GitHub repo](https://github.com/michmech/lemmatization-lists) by [Michal Měchura.](https://github.com/michmech), then converted into csvs for inclusion here.

### Formatting

To create your own list of lemmas for use with the library, create a csv file formatted like the one included here. Use two columns, the first containing your lemmas and the second containing comma-separated forms of the lemmas.


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

# NAME

Text::MathematicalCase - convert to/from mathematical case

# SYNOPSIS

```
use Text::MathematicalCase;        # just mc
say mc "Hello World" :serif:bold;  # 𝐇𝐞𝐥𝐥𝐨 𝐖𝐨𝐫𝐥𝐝

use Text::MathematicalCase :all;   # mc lc uc adverbs
say uc "𝐇𝐞𝐥𝐥𝐨 𝐖𝐨𝐫𝐥𝐝";              # 𝐇𝐄𝐋𝐋𝐎 𝐖𝐎𝐑𝐋𝐃

```

# DESCRIPTION

Text::MathematicalCase is module that exports an `mc` subroutine that implements converting to/from "mathematical case". Just like you can have UPPERCASE or lowercase, you can also have 𝐦𝐚𝐭𝐡𝐞𝐦𝐚𝐭𝐢𝐜𝐚𝐥 𝐜𝐚𝐬𝐞.

"Mathematical case" is basically text expressed in the alphanumeric symbols of the [Mathematical Alphanumeric Symbols](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols) unicode block. In it, several styles are supported:

* serif: serif, 𝐬𝐞𝐫𝐢𝐟 𝐛𝐨𝐥𝐝, 𝑠𝑒𝑟𝑖𝑓 𝑖𝑡𝑎𝑙𝑖𝑐, 𝒔𝒆𝒓𝒊𝒇 𝒃𝒐𝒍𝒅 𝒊𝒕𝒂𝒍𝒊𝒄
* sans-serif: 𝗌𝖺𝗇𝗌-𝗌𝖾𝗋𝗂𝖿, 𝘀𝗮𝗻𝘀-𝘀𝗲𝗿𝗶𝗳 𝗯𝗼𝗹𝗱, 𝘴𝘢𝘯𝘴-𝘴𝘦𝘳𝘪𝘧 𝘪𝘵𝘢𝘭𝘪𝘤, 𝙨𝙖𝙣𝙨-𝙨𝙚𝙧𝙞𝙛 𝙗𝙤𝙡𝙙 𝙞𝙩𝙖𝙡𝙞𝙘
* script: 𝓈𝒸𝓇𝒾𝓅𝓉, 𝓼𝓬𝓻𝓲𝓹𝓽 𝓫𝓸𝓵𝓭
* fraktur: 𝔣𝔯𝔞𝔨𝔱𝔲𝔯, 𝖋𝖗𝖆𝖐𝖙𝖚𝖗 𝖇𝖔𝖑𝖉
* monospace: 𝚖𝚘𝚗𝚘𝚜𝚙𝚊𝚌𝚎
* double-struck: 𝕕𝕠𝕦𝕓𝕝𝕖-𝕤𝕥𝕣𝕦𝕔𝕜

It optionally also exports an `lc` and/or a `uc` subroutine (that perform the same function as the standard `lc` and `uc` subroutines, but are aware of mathematical case characters). And it optionally exports an `adverbs` subroutine that lists all the possible combinations of adverbs that can be passed on to the `mc` subroutine.

This distribution also installs a `mc` script for easy access to the mathematical case functionality.

# SUBROUTINES

## mc

```
say mc "Hello World" :serif:bold;  # 𝐇𝐞𝐥𝐥𝐨 𝐖𝐨𝐫𝐥𝐝

```

Convert a string to mathematical case with the given adverbs.

## lc

```
use Text::MathematicalCase <lc>;
say lc "𝐇𝐞𝐥𝐥𝐨 𝐖𝐨𝐫𝐥𝐝";  # 𝐡𝐞𝐥𝐥𝐨 𝐰𝐨𝐫𝐥𝐝

```

Convert a string to lowercase taking mathematical case into account as well.

## uc

```
use Text::MathematicalCase <uc>;
say uc "𝐇𝐞𝐥𝐥𝐨 𝐖𝐨𝐫𝐥𝐝";  # 𝐇𝐄𝐋𝐋𝐎 𝐖𝐎𝐑𝐋𝐃

```

Convert a string to uppercase taking mathematical case into account as well.

## adverbs

```
use Text::MathematicalCase <adverbs>;
.say for adverbs;
# :double-struck
# :fraktur
# :fraktur:bold
# :monospace
# :sans-serif
# :sans-serif:bold
# :sans-serif:bold:italic
# :sans-serif:italic
# :script
# :script:bold
# :serif
# :serif:bold
# :serif:bold:italic
# :serif:italic

```

# SCRIPTS

## mc

```
$ mc "Hello World" --double-struck
ℍ𝕖𝕝𝕝𝕠 𝕎𝕠𝕣𝕝𝕕

$ mc --double-struck < file-with-text
ℂ𝕠𝕟𝕥𝕖𝕟𝕥 𝕠𝕗 𝕗𝕚𝕝𝕖-𝕨𝕚𝕥𝕙-𝕥𝕖𝕩𝕥

```

The `mc` script either takes a string, or reads from `STDIN` and performs the mathematical case transformation as indicated by its named arguments.

# SEE ALSO

See the [App::Unicode::Mangle](https://modules.raku.org/dist/App::Unicode::Mangle) module for a different approach to this type of functionality.

# AUTHOR

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

Source can be located at: <https://github.com/lizmat/Text-MathematicalCase> . 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 2020, 2021, 2024 Elizabeth Mattijsen

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


## -circumflex-accentff-circumflex-accent.md
^ff^

Combined from primary sources listed below.

# [In Operators](#___top "go to top of document")[§](#(Operators)_infix_^ff^ "direct link")

See primary documentation
[in context](/language/operators#infix_^ff^)
for **infix ^ff^**.

```raku
sub infix:<^ff^>(Mu $a, Mu $b)
```

Works like [ff](/routine/ff), except it does not return `True` for items matching either the stop or start condition (or both).

```raku
my @list = <X A B C Y>;
say $_ if /A/ ff /C/ for @list;    # OUTPUT: «A␤B␤C␤»
say $_ if /A/ ^ff^ /C/ for @list;  # OUTPUT: «B␤»
```

The sed-like version can be found in [`^fff^`](/routine/$CIRCUMFLEX_ACCENTfff$CIRCUMFLEX_ACCENT).

This operator cannot be overloaded, as it's handled specially by the compiler.


## dist_zef-masukomi-Clu.md
(Command LookUp)

Got an overwhelming number of command line scripts and functions? So many you've actually started to forget what options you have available, or what some of them do? Try Clu!

# What does it do?

Clu allows provides a [full text search](https://en.wikipedia.org/wiki/Full-text_search) of the name, description, and details of your scripts. When a script includes a "help" command, Clu will call it and display current usage docs instead of potentially outdated ones from its cache.

Scroll down to see some examples of its output.

## Future looking

The intent is to support [tldr style "cheats"](https://tldr.sh/) for your scripts too. The example TOML template below contains commented out cheats if you feel like writing them now, but Clu currently ignores that data.

Being able to arrow through search results and choose one to see the full details of.

# Installation

Clu is written in [Raku](https://www.raku.org/), and uses the [zef](https://github.com/ugexe/zef) package manager for installation.

If you've already got Raku and zef installed then just run:

`zef install Clu`

## Raku install quick-guide

Use Homebrew to install [Rakudo](https://rakudo.org/). That's the Raku virtual machine. If you install the [Rakudo Star Bundle](https://rakudo.org/star) then [zef](https://github.com/ugexe/zef) will come along for the ride. You can download it from those links, or install it with homebrew.

```
brew install rakudo-star

```

Now, go back and run the `zef install` command above.

# Usage

```
Usage:
  clu add <path>
  clu find [<search_strings> ...]
  clu list
  clu remove <command_name>
  clu show <command_name>
  clu template <destination>
  clu update <path>

```

## Documenting a new Command

The first step is to create a [TOML file](https://toml.io/en/) for each cli tool you wish to document. Clu doesn't care where these live. My advice is to put them alongside your script, so that when you share your script with others, it can go along for the ride, even if they're not using Clu, TOML is still very readable.

Clu doesn't care what the file is named, so long as it ends with `.toml` but personally I've been using the convention of `<command_name>.meta.toml` and putting it in the same directory as the command I'm documenting.

The `template` comand will generate a TOML file for you where you just have to fill in the blanks.

1. run `clu template path/to/my_command.meta.toml`

For example: If you have a `foo` command you'd make a `foo.meta.toml` file. It doesn't matter if you're documenting an executable or a shell function.

1. Edit your new TOML file.
2. run `clu add path/to/my_command.meta.toml`

That's it. If you ever need to update / change the documentation just edit the TOML file and run `clu update <path/to/my_command.meta.toml>`. It'll find the command with the matching name in the database, and replace it.

## Showing a command

`clu show <command_name>` will display the name, description, and usage of the specified command (if found).

Output looks like this:

```
❯ clu show rg-ignores
rg-ignores : finds files that rg may be using to ignore patterns

USAGE: rg-ignores <path>

       Use me when rg isn't finding something you expect
       and rg --hidden isn't helping.
       Looks for files that RipGrep will consult
       in order to find patterns to ignore.

       Note: using --hidden --no-ignore is a short term fix

--------------------
type: executable
lang: bash
location: /Users/masukomi/bin/rg-ignores

source repo: https://github.com/masukomi/masuconfigs
source url: https://github.com/masukomi/masuconfigs/blob/master/bin/rg-ignores

```

## Finding a command

`clu find <search terms>` Don't bother quoting the search terms. Something like `clu find foo bar baz` is fine.

Clu will perform a full text search for your terms on the name, description, and language fields, and display the results.

If you want more details, run `clu show <command name>` for the command you've found.

Output looks like this:

```
❯ clu find find
rg-ignores          | finds files that rg may be using to ignore patterns
git-oldest-ancestor | finds the oldest common ancestor between two git treeishes

```

## Listing all commands

`clu list` will list everything for you. Output looks like
this:

```
❯ clu list
backtrace_details   | Pairs a backtrace with the corresponding lines of code
bak                 | bak moves or copies the proffered file to a .back version
blankless           | converts whitespace-only lines to empty lines.
color_test          | outputs a smooth gradient band along the RGB spectrum
git-branch-pr       | Shows or opens the Pull Request for the current branch
git-oldest-ancestor | finds the oldest common ancestor between two git treeishes
hr                  | outputs a horizontal rule the width of your terminal
is_brewed           | indicates if a package is installed via homebrew
rg-ignores          | finds files that rg may be using to ignore patterns
watch_when          | Polls a command and reports when its output changes

```

## Updating a command

`clu update <path/to/my_command.meta.toml>` will find the existing command with the name specified in the TOML and update its data. If you have changed the name of the command you'll need to remove and add instead of update.

## Removing a command

`clu remove <command_name>` will remove the command with the
specified name.

## Syncing between machines

There's no inherent syncing here. Sorry. You can copy the db from `~/.config/clu/database.db` to another machine, or, you can boot it up on a new system and run something like this to ingest all your toml files.

```
find ~/folder/with/my/clu_toml_files -name "*.meta.toml" -exec clu add '{}' \;

```

# LICENSE

Copyright 2022 [Kay Rhodes](https://masukomi.org) (a.k.a. masukomi). Distributed under the MIT License.