## io-guide.md
Input/Output the definitive guide

Correctly use Raku IO

# [The basics](#Input/Output_the_definitive_guide "go to top of document")[§](#The_basics "direct link")

The vast majority of common IO work is done by the [`IO::Path`](/type/IO/Path) type. If you want to read from or write to a file in some form or shape, this is the class you want. It abstracts away the details of filehandles (or "file descriptors") and so you mostly don't even have to think about them.

Behind the scenes, [`IO::Path`](/type/IO/Path) works with [`IO::Handle`](/type/IO/Handle), a class which you can use directly if you need a bit more control than what [`IO::Path`](/type/IO/Path) provides. When working with other processes, e.g. via [`Proc`](/type/Proc) or [`Proc::Async`](/type/Proc/Async) types, you'll also be dealing with a *subclass* of [`IO::Handle`](/type/IO/Handle): the [`IO::Pipe`](/type/IO/Pipe).

Lastly, you have the [`IO::CatHandle`](/type/IO/CatHandle), as well as [`IO::Spec`](/type/IO/Spec) and its subclasses, that you'll rarely, if ever, use directly. These classes give you advanced features, such as operating on multiple files as one handle, or low-level path manipulations.

Along with all these classes, Raku provides several subroutines that let you indirectly work with these classes. These come in handy if you like functional programming style or in Raku one liners.

While [`IO::Socket`](/type/IO/Socket) and its subclasses also have to do with Input and Output, this guide does not cover them.

# [Navigating paths](#Input/Output_the_definitive_guide "go to top of document")[§](#Navigating_paths "direct link")

## [What's an IO::Path anyway?](#Input/Output_the_definitive_guide "go to top of document")[§](#What's_an_IO::Path_anyway? "direct link")

To represent paths as either files or directories, use [`IO::Path`](/type/IO/Path) type. The simplest way to obtain an object of that type is to coerce a [`Str`](/type/Str) by calling the [`.IO`](/routine/IO) method on it:

```raku
say 'my-file.txt'.IO; # OUTPUT: «"my-file.txt".IO␤»
```

It may seem like something is missing here—there is no volume or absolute path involved—but that information is actually present in the object. You can see it by using [`.raku`](/routine/raku) method:

```raku
say 'my-file.txt'.IO.raku;
# OUTPUT: «IO::Path.new("my-file.txt", :SPEC(IO::Spec::Unix), :CWD("/home/camelia"))␤»
```

The two extra attributes—`SPEC` and `CWD`—specify what type of operating system semantics the path should use as well as the "current working directory" for the path, i.e. if it's a relative path, then it's relative to that directory.

This means that regardless of how you made one, an [`IO::Path`](/type/IO/Path) object technically always refers to an absolute path. This is why its [`.absolute`](/routine/absolute) and [`.relative`](/routine/relative) methods return [`Str`](/type/Str) objects and they are the correct way to stringify a path.

However, don't be in a rush to stringify anything. Pass paths around as [`IO::Path`](/type/IO/Path) objects. All the routines that operate on paths can handle them, so there's no need to convert them.

## [Path parts](#Input/Output_the_definitive_guide "go to top of document")[§](#Path_parts "direct link")

Given a local file name, it's very easy to get its components. For example, we have a file, "financial.data", in some directory, "/usr/local/data". Use Raku to analyze its path:

```raku
my $fname = "financial.data";
# Stringify the full path name
my $f = $fname.IO.absolute;
say $f;
#   OUTPUT: «/usr/local/data/financial.data␤»
# Stringify the path's parts:
say $f.IO.dirname;                       # OUTPUT: «/usr/local/data␤»
say $f.IO.basename;                      # OUTPUT: «financial.data␤»
# And the basename's parts:
# Use a method for the extension:
say $f.IO.extension;                     # OUTPUT: «data␤»
# Remove the extension by redefining it:
say ($f.IO.extension("")).IO.basename;   # OUTPUT: «financial␤»

```

## [Working with files](#Input/Output_the_definitive_guide "go to top of document")[§](#Working_with_files "direct link")

### [Writing into files](#Input/Output_the_definitive_guide "go to top of document")[§](#Writing_into_files "direct link")

#### [Writing new content](#Input/Output_the_definitive_guide "go to top of document")[§](#Writing_new_content "direct link")

Let's make some files and write and read data from them! The [`spurt`](/routine/spurt) and [`slurp`](/routine/slurp) routines write and read the data in one chunk respectively. Unless you're working with very large files that are difficult to store entirely in memory all at the same time, these two routines are for you.

```raku
"my-file.txt".IO.spurt: "I ♥ Raku!";

```

The code above creates a file named `my-file.txt` in the current directory and then writes text `I ♥ Raku!` into it. If Raku is your first language, celebrate your accomplishment! Try to open the file you created with a text editor to verify what you wrote with your program. If you already know some other language, you may be wondering if this guide missed anything like handling encoding or error conditions.

However, that is all the code you need. The string will be encoded in `utf-8` encoding by default and the errors are handled via the [`Failure`](/type/Failure) mechanism: these are exceptions you can handle using regular conditionals. In this case, we're letting all potential [`Failure`](/type/Failure)s get sunk after the call and so any [`Exceptions`](/type/Exception) they contain will be thrown.

#### [Appending content](#Input/Output_the_definitive_guide "go to top of document")[§](#Appending_content "direct link")

If you wanted to add more content to the file we created in the previous section, you could note the [`spurt` documentation](/routine/spurt) mentions `:append` as one of its argument options. However, for finer control, let's get ourselves an [`IO::Handle`](/type/IO/Handle) to work with:

```raku
my $fh = 'my-file.txt'.IO.open: :a;
$fh.print: "I count: ";
$fh.print: "$_ " for ^10;
$fh.close;

```

The [`.open`](/routine/open) method call opens our [`IO::Path`](/type/IO/Path) and returns an [`IO::Handle`](/type/IO/Handle). We passed `:a` as argument, to indicate we want to open the file for writing in append mode.

In the next two lines of code, we use the usual [`.print`](/routine/print) method on that [`IO::Handle`](/type/IO/Handle) to print a line with 11 pieces of text (the `'I count: '` string and 10 numbers). Note that, once again, [`Failure`](/type/Failure) mechanism takes care of all the error checking for us. If the [`.open`](/routine/open) fails, it returns a [`Failure`](/type/Failure), which will throw when we attempt to call method the [`.print`](/routine/print) on it.

Finally, we close the [`IO::Handle`](/type/IO/Handle) by calling the [`.close`](/routine/close) method on it. It is *important that you do it*, especially in large programs or ones that deal with a lot of files, as many systems have limits to how many files a program can have open at the same time. If you don't close your handles, eventually you'll reach that limit and the [`.open`](/routine/open) call will fail. Note that unlike some other languages, Raku does not use reference counting, so the filehandles **are NOT closed** when the scope they're defined in is left. They will be closed only when they're garbage collected and failing to close the handles may cause your program to reach the file limit *before* the open handles get a chance to get garbage collected.

### [Reading from files](#Input/Output_the_definitive_guide "go to top of document")[§](#Reading_from_files "direct link")

#### [Using IO::Path](#Input/Output_the_definitive_guide "go to top of document")[§](#Using_IO::Path "direct link")

We've seen in previous sections that writing stuff to files is a single-line of code in Raku. Reading from them, is similarly easy:

```raku
say 'my-file.txt'.IO.slurp;        # OUTPUT: «I ♥ Raku!␤»
say 'my-file.txt'.IO.slurp: :bin;  # OUTPUT: «Buf[uint8]:0x<49 20 E2 99 A5 20 52 61 6B 75 21>␤»

```

The [`.slurp`](/routine/slurp) method reads entire contents of the file and returns them as a single [`Str`](/type/Str) object, or as a [`Buf`](/type/Buf) object, if binary mode was requested, by specifying `:bin` named argument.

Since [slurping](/routine/slurp) loads the entire file into memory, it's not ideal for working with huge files.

The [`IO::Path`](/type/IO/Path) type offers two other handy methods: [`.words`](/type/IO/Path#method_words) and [`.lines`](/type/IO/Path#method_lines) that lazily read the file in smaller chunks and return [`Seq`](/type/Seq) objects that (by default) don't keep already-consumed values around.

Here's an example that finds lines in a text file that mention Raku and prints them out. Despite the file itself being too large to fit into available [RAM](https://en.wikipedia.org/wiki/Random-access_memory), the program will not have any issues running, as the contents are processed in small chunks:

```raku
.say for '500-PetaByte-File.txt'.IO.lines.grep: *.contains: 'Raku';

```

Here's another example that prints the first 100 words from a file, without loading it entirely:

```raku
.say for '500-PetaByte-File.txt'.IO.words: 100

```

Note that we did this by passing a limit argument to [`.words`](/type/IO/Path#method_words) instead of, say, using [a list indexing operation](/language/operators#index-entry-array_indexing_operator-array_subscript_operator-array_indexing_operator). The reason for that is there's still a filehandle in use under the hood, and until you fully consume the returned [`Seq`](/type/Seq), the handle will remain open. If nothing references the [`Seq`](/type/Seq), eventually the handle will get closed, during a garbage collection run, but in large programs that work with a lot of files, it's best to ensure all the handles get closed right away. So, you should always ensure the [`Seq`](/type/Seq) from [`IO::Path`](/type/IO/Path)'s [`.words`](/type/IO/Path#method_words) and [`.lines`](/type/IO/Path#method_lines) methods is [fully reified](/language/glossary#Reify); and the limit argument is there to help you with that.

#### [Using IO::Handle](#Input/Output_the_definitive_guide "go to top of document")[§](#Using_IO::Handle "direct link")

You can read from files using the [`IO::Handle`](/type/IO/Handle) type; this gives you a finer control over the process.

```raku
given 'some-file.txt'.IO.open {
    say .readchars: 8;  # OUTPUT: «I ♥ Raku␤»
    .seek: 1, SeekFromCurrent;
    say .readchars: 15;  # OUTPUT: «I ♥ Programming␤»
    .close
}

```

The [`IO::Handle`](/type/IO/Handle) gives you [.read](/type/IO/Handle#method_read), [.readchars](/type/IO/Handle#method_readchars), [.get](/type/IO/Handle#routine_get), [.getc](/type/IO/Handle#routine_getc), [.words](/type/IO/Handle#routine_words), [.lines](/type/IO/Handle#routine_lines), [.slurp](/type/IO/Handle#method_slurp), [.comb](/type/IO/Handle#method_comb), [.split](/type/IO/Handle#method_split), and [.Supply](/type/IO/Handle#method_Supply) methods to read data from it. Plenty of options; and the catch is you need to close the handle when you're done with it.

Unlike some languages, the handle won't get automatically closed when the scope it's defined in is left. Instead, it'll remain open until it's garbage collected. To make the closing business easier, some of the methods let you specify a `:close` argument, you can also use the [`will leave` trait](/language/phasers#index-entry-will_trait), or the `does auto-close` trait provided by the [`Trait::IO`](https://raku.land/zef:raku-community-modules/Trait::IO) module.

# [The wrong way to do things](#Input/Output_the_definitive_guide "go to top of document")[§](#The_wrong_way_to_do_things "direct link")

This section describes how NOT to do Raku IO.

## [Leave $\*SPEC alone](#Input/Output_the_definitive_guide "go to top of document")[§](#Leave_$*SPEC_alone "direct link")

You may have heard of [`$*SPEC`](/language/variables#Dynamic_variables) and seen some code or books show its usage for splitting and joining path fragments. Some of the routine names it provides may even look familiar to what you've used in other languages.

However, unless you're writing your own IO framework, you almost never need to use [`$*SPEC`](/language/variables#Dynamic_variables) directly. [`$*SPEC`](/language/variables#Dynamic_variables) provides low-level stuff and its use will not only make your code tough to read, you'll likely introduce security issues (e.g. null characters)!

The [`IO::Path`](/type/IO/Path) type is the workhorse of Raku world. It caters to all the path manipulation needs as well as provides shortcut routines that let you avoid dealing with filehandles. Use that instead of the [`$*SPEC`](/language/variables#Dynamic_variables) stuff.

Tip: you can join path parts with `/` and feed them to [`IO::Path`](/type/IO/Path)'s routines; they'll still do The Right Thing™ with them, regardless of the operating system.

```raku
# WRONG!! TOO MUCH WORK!
my $fh = open $*SPEC.catpath: '', 'foo/bar', $file;
my $data = $fh.slurp;
$fh.close;

```

```raku
# RIGHT! Use IO::Path to do all the dirty work
my $data = 'foo/bar'.IO.add($file).slurp;

```

However, it's fine to use it for things not otherwise provided by [`IO::Path`](/type/IO/Path). For example, the [`.devnull` method](/routine/devnull):

```raku
{
    temp $*OUT = open :w, $*SPEC.devnull;
    say "In space no one can hear you scream!";
}
say "Hello";

```

## [Stringifying IO::Path](#Input/Output_the_definitive_guide "go to top of document")[§](#Stringifying_IO::Path "direct link")

Don't use the `.Str` method to stringify [`IO::Path`](/type/IO/Path) objects, unless you just want to display them somewhere for information purposes or something. The `.Str` method returns whatever basic path string the [`IO::Path`](/type/IO/Path) was instantiated with. It doesn't consider the value of the [`$.CWD` attribute](/type/IO/Path#attribute_CWD). For example, this code is broken:

```raku
my $path = 'foo'.IO;
chdir 'bar';
# WRONG!! .Str DOES NOT USE $.CWD!
run <tar -cvvf archive.tar>, $path.Str;

```

The [`chdir`](/routine/chdir) call changed the value of the current directory, but the `$path` we created is relative to the directory before that change.

However, the [`IO::Path`](/type/IO/Path) object *does* know what directory it's relative to. We just need to use [`.absolute`](/routine/absolute) or [`.relative`](/routine/relative) to stringify the object. Both routines return a [`Str`](/type/Str) object; they only differ in whether the result is an absolute or relative path. So, we can fix our code like this:

```raku
my $path = 'foo'.IO;
chdir 'bar';
# RIGHT!! .absolute does consider the value of $.CWD!
run <tar -cvvf archive.tar>, $path.absolute;
# Also good:
run <tar -cvvf archive.tar>, $path.relative;

```

## [Be mindful of $\*CWD](#Input/Output_the_definitive_guide "go to top of document")[§](#Be_mindful_of_$*CWD "direct link")

While usually out of view, every [`IO::Path`](/type/IO/Path) object, by default, uses the current value of [`$*CWD`](/language/variables#Dynamic_variables) to set its [`$.CWD` attribute](/type/IO/Path#attribute_CWD). This means there are two things to pay attention to.

### [temp the $\*CWD](#Input/Output_the_definitive_guide "go to top of document")[§](#temp_the_$*CWD "direct link")

This code is a mistake:

```raku
# WRONG!!
my $*CWD = "foo".IO;

```

The `my $*CWD` made [`$*CWD`](/language/variables#Dynamic_variables) undefined. The [`.IO`](/routine/IO) coercer then goes ahead and sets the [`$.CWD` attribute](/type/IO/Path#attribute_CWD) of the path it's creating to the stringified version of the undefined `$*CWD`; an empty string.

The correct way to perform this operation is use [`temp`](/routine/temp) instead of `my`. It'll localize the effect of changes to [`$*CWD`](/language/variables#Dynamic_variables), just like `my` would, but it won't make it undefined, so the [`.IO`](/routine/IO) coercer will still get the correct old value:

```raku
temp $*CWD = "foo".IO;

```

Better yet, if you want to perform some code in a localized [`$*CWD`](/language/variables#Dynamic_variables), use the [`indir` routine](/routine/indir) for that purpose.


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

# NAME

Text::Utils - Miscellaneous text utilities

# SYNOPSIS

```
# Export individual routines or :ALL
use Text::Utils :strip-comment;
my $text = q:to/HERE/;
    any kind of text, including code"; # some comment
    my $s = 'foo'; # another comment
    HERE

for $text.lines -> $line is copy {
    $line = strip-comment $line;
    say $line;
}
# OUTPUT with comments removed:
any kind of text, including code;
my $s = 'foo';

```

# DESCRIPTION

The module contains several routines to make text handling easier for module and program authors. The routines:

| Name | Notes |
| --- | --- |
| commify |  |
| count-substrs |  |
| list2text |  |
| normalize-string | alias 'normalize-text' |
| sort-list |  |
| split-line | aliases 'splitstr', 'split-str' |
| strip-comment |  |
| wrap-paragraph | 'width' is in PS points |
| wrap-text | 'width' is in number of chars |

Following is a short synopsis and signature for each of the routines.

### commify

This routine was originally ported from the Perl version in the *The Perl Cookbook, 2e*.

The routine adds commas to a number to separate multiples of a thousand. For example, given an input of `1234.56`, the routine returns `1,234.56`.

As an improvement, if real numbers are input, the routine returns the number stringified with two decimal places. The user may specify the desired number with the new `:$decimals` named argument.

The signature:

```
sub commify($num, :$decimals --> Str) is export(:commify)
{...}

```

### count-substrs

Count instances of a substring in a string.

The signature:

```
sub count-substrs(
    Str:D $string,
    Str:D $substr
    --> UInt
    ) is export(:count-substrs)
{...}

```

### list2text

Turn a list into a text string for use in a document.

For example, this list `1 2 3` becomes either this `"1, 2, and 3"` (the default result) or this `"1, 2 and 3"` (if the `$optional-comma` named variable is set to false). The default result uses the so-called *Oxford Comma* which is not popular among some writers, but those authors may change the default behavior by permanently by defining the environment variable `TEXT_UTILS_NO_OPTIONAL_COMMA`.

The signature:

```
sub list2text(
    @list,
    :$optional-comma is copy = True
    ) is export(:list2text)
{...}

```

### normalize-text

Alias for 'normalize-string'.

### normalize-string

This routine trims a string and collapses multiple whitespace characters (including tabs and newlines) into one.

The signature:

```
subset Kn of Any where { $_ ~~ /^ :i [0|k|n]   /}; #= keep or normalize
subset Sn of Any where { $_ ~~ /^ :i [0|n|s|t] /}; #= collapse all contiguous ws
sub normalize-string(
    Str:D $str is copy
    Kn :t(:$tabs)=0,           #= keep or normalize
    Kn :n(:$newlines)=0,       #= keep or normalize
    Sn :c(:$collapse-ws-to)=0, #= collapse all contiguous ws
                               #=   to one char
    --> Str) is export(:normalize-string)
{...}

```

'Normalization' is the process of converting a contiguous sequence of space characters into a single character. The three space characters recognized are " " (0x20, 'space'), "\t" (0x09, tab), and "\n" (0x0A, 'newline'). The default algorithm to do that for a string `$s` is `$s = s:g/ \s ** 2 / /`.

This routine gives several options to control how the target string is 'normalized'. First, the user may choose one or more of the space character types to be normalized individually. Second, the user may choose to 'collapse' all space characters to one of the three types.

Given a string with spaces, tabs, and newlines:

```
my $s = " 1   \t\t\n\n 2 \n\t  3  ";

```

The default:

```
say normalize-string($s) # OUTPUT: «1 2 3␤»

```

Normalize each tab:

```
say normalize-string($s, :t<n>) # OUTPUT: «1 \t\n\n 2 \n\t 3␤»

```

Normalize each newline:

```
say normalize-string($s, :n<n>) # OUTPUT: «1 \t\t\n 2 \n\t 3␤»

```

Normalize each tab and newline:

```
say normalize-string($s, :t<n>, :n<n>) # OUTPUT: «1 \t\n 2 \n\t 3␤»

```

Collapse to a space:

```
say normalize-string($s, :c<s>) # OUTPUT: «1 2 3␤»

```

Collapse to a tab:

```
say normalize-string($s, :c<t>) # OUTPUT: «1\t2\t3␤»

```

Collapse to a newline:

```
say normalize-string($s, :c<n>) # OUTPUT: «1\n2\n3␤»

```

Notice that in the normalization routines, spaces (' ') are always normalized, even when tabs and newlines are normalized separately.

Also notice all strings are normally trimmed of leading and trailing whitespace regardless of the option used. However, option `:no-trim` protects the input string from any such trimming. Consider the first example from above:

```
my $s = " 1   \t\t\n\n 2 \n\t  3  ";

```

Using the 'no-trim' option:

```
say normalize-string($s, :no-trim) # OUTPUT: « 1 2 3  ␤»

```

### sort-list

```
#  StrLength, LengthStr, Str, Length, Number
enum Sort-type is export(:sort-list) < SL LS SS LL N >;
sub sort-list(@list, :$type = SL, :$reverse --> List) is export(:sort-list)
{...}

```

By default, this routine sorts all lists by word length, then by Str order. The order by length is by the shortest abbreviation first unless the `:$reverse` option is used.

The routine's output can be modified for other uses by entering the `:$type` parameter to choose another of the `enum Sort-type`s.

### split-line

Splits a string into two pieces.

Inputs are the string to be split, the split character or string, maximum length, a starting position for the search, and the search direction (normally forward unless the `:$rindex` option is `True`).

An additional option, `:$break-after`, causes the split to be delayed to the position after the input break string on a normal forward split.

It returns the two parts of the split string. The second part will be shortened to the `:$max-line-length` value if its entered value is greater than the default zero.

The signature:

```
sub split-line(
    Str:D $line is copy,
    Str:D $brk,
    UInt  :$max-line-length = 0,
    UInt  :$start-pos       = 0,
    Bool  :$rindex          = False,
    Bool  :$break-after     = False,
    --> List) is export(:split-line)
{...}

```

### strip-comment

Strip the comment from an input text line, save comment if requested, normalize returned text if requested.

The routine returns a string of text with any comment stripped off. Note the designated character will trigger the strip even though it is escaped or included in quotes. Also returns the comment, including the comment character, if requested. All returned text is normalized if requested. Any returned comment will also be normalized if the `normalize-all` option is used in place of `normalize`.

The signature:

```
sub strip-comment(
    $line is copy,                # string of text with possible comment
    :mark(:$comment-char) = '#',  # desired comment character indicator
                                  #   (with alias :$comment-char)
    :$save-comment,               # if true, return the comment
    :$normalize,                  # if true, normalize returned string
    :$normalize-all,              # if true, normalize returned string
                                  #   and also normalize any saved comment
    :$last,                       # if true, use the last instead of first
                                  #   comment character
    :$first,                      #= if true, the comment char must be the
                                  #=   first non-whitespace character on
                                  #=   the line; otherwise, the line is
                                  #=   returned as is
    ) is export(:strip-comment)
{...}

```

Note the default return is the returned string without any comment. However, if you use the `save-comment` option, a two-element list is returned: `($string, $comment)` (either element may be "" depending upon the input text line).

### wrap-paragraph

This routine wraps a list of words into a paragraph with a maximum line width in characters (default: 78), and returns a list of the new paragraph's lines formatted as desired. An option, `:$para-pre-text`, used in conjunction with `:$para-indent`, is very useful for use in auto-generation of code. For example, given this chunk of text describing a following PDF method `MoveTo(x, y)`:

```
my $str = q:to/HERE/;
Begin a new sub-path by moving the current point to coordinates (x,
y), omitting any connecting line segment. If the previous path
construction operator in the current path was also m, the new m
overrides it.
HERE

```

Run that string through the sub to see the results:

```
my @para = wrap-paragraph $str.lines, :para-pre-text('#| '), :para-indent(4);
.say for @para;

```

yields:

```
    #| Begin a new sub-path by moving the current point to coordinates (x, y),
    #| omitting any connecting line segment. If the previous path construction
    #| operator in the current path was also m, the new m overrides it.

```

The signature:

```
multi sub wrap-paragraph(
    @text,
    UInt :$max-line-length     = 78,
    #------------------------------#
    UInt :$para-indent         = 0,
    UInt :$first-line-indent   = 0,
    UInt :$line-indent         = 0,
    #------------------------------#
    Str  :$para-pre-text       = '',
    Str  :$first-line-pre-text = '',
    Str  :$line-pre-text       = '',
    #------------------------------#
    :$debug,
    --> List) is export(:wrap-paragraph)
{...}
multi sub wrap-paragraph(
    $text,
    # ... other args same as the other multi
    --> List) is export(:wrap-paragraph)
{...}

```

### wrap-text

This routine is used in creating PostScript PDF or other output formats where blocks (e.g., paragraphs) need to be wrapped to a specific maximum width based on the font face and font size to be used. Note it has all the options of the **wrap-paragraph** routine except the `:width` is expressed in PostScript points (72 per inch) as is the `:font-size`. The default `:width` is 468 points, the length of a line on a Letter paper, portrait orientation, with one-inch margins on all sides.

The fonts currently handled are the the 14 PostScript and PDF *Core Fonts*:

|  |
| --- |
| Courier |
| Courier-Bold |
| Courier-Oblique |
| Courier-BoldOblique |
| Helvetica |
| Helvatica-Bold |
| Helvetica-Oblique |
| Helvatica-BoldOblique |
| Times-Roman |
| Times-Bold |
| Times-Italic |
| Times-BoldItalic |
| Symbol |
| Zaphdingbats |

```
multi sub wrap-text(
    @text,
    Real :$width               = 468, #= PS points for 6.5 inches
         :$font-name           = 'Times-Roman',
    Real :$font-size           = 12,
    #------------------------------#
    UInt :$para-indent         = 0,
    UInt :$first-line-indent   = 0,
    UInt :$line-indent         = 0,
    #------------------------------#
    Str  :$para-pre-text       = '',
    Str  :$first-line-pre-text = '',
    Str  :$line-pre-text       = '',
    #------------------------------#
    :$debug,
    --> List) is export(:wrap-text)
{...}
multi sub wrap-text(
    $text,
    # ... other args same as the other multi
    --> List) is export(:wrap-text)
{...}

```

# AUTHOR

Tom Browder [tbrowder@cpan.org](mailto:tbrowder@cpan.org)

# COPYRIGHT AND LICENSE

Copyright © 2019-2024 Tom Browder

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


## dist_cpan-RBT-Text-Diff.md
# NAME

Text::Diff - Perform diffs on files and record sets

# SYNOPSIS

```
  use Text::Diff;

  # Mix and match filenames, strings, file handles, producer subs,
  # or arrays of records; returns diff in a string.
  # WARNING: can return B<large> diffs for large files.
  my $diff = diff $string1,   $string2, output-style => Context;
  my $diff = diff '/tmp/log1.txt'.IO.open, '/tmp/log2.txt'.IO.open;
  my $diff = diff @records1,  @records2;

  # May also mix input types:
  my $diff = diff @records1, $string2;

```

# DESCRIPTION

`diff()` provides a basic set of services akin to the GNU "diff"
utility. It is not anywhere near as feature complete as GNU "diff", but
it is better integrated with Perl and available on all platforms. It is
often faster than shelling out to a system's "diff" executable for small
files, and generally slower on larger files.

Relies on Algorithm::Diff for, well, the algorithm. This may not produce
the same exact diff as a system's local "diff" executable, but it will
be a valid diff and comprehensible by "patch".

```
diff($a, $b, Int :offset-a = 0, Int :offset-b = 0, Str :filename-a = 'A', Str :filename-b = 'B',
     Instant :mtime-a, Instant :mtime-b, OutputStyle :output-style = Unified,
     Int :context-lines = 3 --> Str)

```

# OPTIONS

`diff()` takes two parameters from which to draw input and a set of
options to control it's output. The options are:

## context-lines

How many lines before and after each diff to display. Defaults to 3.

## filename-a, filename-b, mtime-a, mtime-b

The name of the file and the modification time "files"

These are filled in automatically for each file when diff() is
passed a filename, unless a defined value is passed in.

If a filename is not passed in and filename-a and filename-b are not
provided then "A" and "B" will be used as defaults.

## offset-a, offset-b

The index of the first line / element. These default to 1 for all
parameter types except ARRAY references, for which the default is 0.
This is because ARRAY references are presumed to be data structures,
while the others are line oriented text.

## output-style

`Unified`, `Context`, and `Table`.

Defaults to "Unified" (unlike standard "diff", but Unified is what's
most often used in submitting patches and is the most human readable
of the three.

`Table` presents a left-side/right-side comparison of the file contents.
This will not worth with patch but it is very human readable for thin
files.

```
      +--+----------------------------------+--+------------------------------+
      |  |../Test-Differences-0.2/MANIFEST  |  |../Test-Differences/MANIFEST  |
      |  |Thu Dec 13 15:38:49 2001          |  |Sat Dec 15 02:09:44 2001      |
      +--+----------------------------------+--+------------------------------+
      |  |                                  * 1|Changes                       *
      | 1|Differences.pm                    | 2|Differences.pm                |
      | 2|MANIFEST                          | 3|MANIFEST                      |
      |  |                                  * 4|MANIFEST.SKIP                 *
      | 3|Makefile.PL                       | 5|Makefile.PL                   |
      |  |                                  * 6|t/00escape.t                  *
      | 4|t/00flatten.t                     | 7|t/00flatten.t                 |
      | 5|t/01text_vs_data.t                | 8|t/01text_vs_data.t            |
      | 6|t/10test.t                        | 9|t/10test.t                    |
      +--+----------------------------------+--+------------------------------+

```

This format also goes to some pains to highlight "invisible" characters
on differing elements by selectively escaping whitespace:

```
      +--+--------------------------+--------------------------+
      |  |demo_ws_A.txt             |demo_ws_B.txt             |
      |  |Fri Dec 21 08:36:32 2001  |Fri Dec 21 08:36:50 2001  |
      +--+--------------------------+--------------------------+
      | 1|identical                 |identical                 |
      * 2|        spaced in         |        also spaced in    *
      * 3|embedded space            |embedded        tab       *
      | 4|identical                 |identical                 |
      * 5|        spaced in         |\ttabbed in               *
      * 6|trailing spaces\s\s\n     |trailing tabs\t\t\n       *
      | 7|identical                 |identical                 |
      * 8|lf line\n                 |crlf line\r\n             *
      * 9|embedded ws               |embedded\tws              *
      +--+--------------------------+--------------------------+

```

## LIMITATIONS

Since the module relies on Raku's internal line splitting which processes files as expected but
hides the details. Features such as notification about new-line at end-of-file, or differences
between \n and \r\n lines are not reported.

This module also does not (yet) provide advanced GNU diff features such as ignoring blank lines
or whitespace.

## AUTHOR

Adam Kennedy [adamk@cpan.org](mailto:adamk@cpan.org)

Barrie Slaymaker [barries@slaysys.com](mailto:barries@slaysys.com)

Ported from CPAN5 By: Rod Taylor [rbt@cpan.org](mailto:rbt@cpan.org)

## LICENSE

You can use and distribute this module under the terms of the The Artistic License 2.0. See the LICENSE file included in this distribution for complete details.


## dist_zef-grizzlysmit-App-pack.raku.md
# App::pack

# Module Pack

## Table of Contents

* [NAME](#name)
* [AUTHOR](#author)
* [VERSION](#version)
* [TITLE](#title)
* [SUBTITLE](#subtitle)
* [COPYRIGHT](#copyright)
* [Introduction](#introduction)

  * [Motivation](#motivation)
* [Fix](#fix)

# NAME

App::pack

# AUTHOR

Francis Grizzly Smit ([grizzly@smit.id.au](mailto:grizzly@smit.id.au))

# VERSION

v0.1.0

# TITLE

pack

# SUBTITLE

A Raku program to manage the use of **gnome-extensions pack**, it has too many arguments this makes it easy.

# COPYRIGHT

GPL V3.0+ [LICENSE](https://github.com/grizzlysmit/Usage-Utils/blob/main/LICENSE)

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

# Introduction

This is a Raku program to manage the use of **gnome-extensions pack**, it has too many arguments this makes it easy.

## Motivation

The command **gnome-extensions pack** has too many arguments this takes care of that making it easier to package up your gnome-shell extensions.

### pack

```
pack.raku --help

Usage:
  pack.raku do <dir>   [-f|--force]
  pack.raku create <package-dir>  [<extra-sources> ...] [-s|--schema=<Str>] [-p|--podir=<Str>] [-g|--gettext-domain=<Str>] [-o|--out-dir=<Str>] [-f|--force]
  pack.raku add <package-dir>  [<extra-sources> ...] [-s|--schema=<Str>] [-p|--podir=<Str>] [-g|--gettext-domain=<Str>] [-o|--out-dir=<Str>] [-f|--force] [-F|--stomp-force] [-S|--stomp]
  pack.raku set schema <package-dir> <schema-value>
  pack.raku set podir <package-dir> <podir-value>
  pack.raku set gettext-domain <package-dir> <gettext-domain-value>
  pack.raku set out-dir <package-dir> <out-dir-value>
  pack.raku set force <package-dir> <force-value>
  pack.raku add-extra-sources <package-dir>  [<extra-sources> ...]
  pack.raku set package-dir <package-dir> <package-dir-value>
  pack.raku set extra-sources <package-dir>  [<extra-sources> ...]
  pack.raku append extra-sources <package-dir>  [<extra-sources> ...]
  pack.raku remove schema <package-dir>
  pack.raku remove podir <package-dir>
  pack.raku remove gettext-domain <package-dir>
  pack.raku remove out-dir <package-dir>
  pack.raku remove extra-sources <package-dir>
  pack.raku get schema <package-dir>
  pack.raku get podir <package-dir>
  pack.raku get gettext-domain <package-dir>
  pack.raku get out-dir <package-dir>
  pack.raku get extra-sources <package-dir>
  pack.raku get force <package-dir>
  pack.raku get package-dir <package-dir>
  pack.raku alias add <key> <target>   [-s|--set|--force] [-c|--comment=<Str>]
  pack.raku alias do <key>   [-f|--force]
  pack.raku edit configs
  pack.raku list keys  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku list all  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku delete   [<keys> ...] [-d|--delete|--do-not-trash
  pack.raku del   [<keys> ...] [-d|--delete|--do-not-trash]
  pack.raku trash   [<keys> ...]
  pack.raku tidy file
  pack.raku comment <key> <comment>   [-k|--kind=<Str where \{ ... } >]
  pack.raku list trash  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku empty trash
  pack.raku undelete   [<keys> ...]
  pack.raku show stats  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku show statistics  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku backup db    [-w|--win-format|--use-windows-formating]
  pack.raku restore db  [<restore-from>]
  pack.raku menu restore db  [<message>]  [-c|--color|--colour] [-s|--syntax]
  pack.raku list db backups  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku list editors    [-f|--prefix=<Str>] [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku editors stats  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku list editors backups  [<prefix>]  [-c|--color|--colour] [-s|--syntax] [-l|--page-length[=Int]] [-p|--pattern=<Str>] [-e|--ecma-pattern=<Str>]
  pack.raku backup editors    [-w|--use-windows-formatting]
  pack.raku restore editors <restore-from>
  pack.raku set editor <editor> [<comment>]
  pack.raku set override GUI_EDITOR <value> [<comment>]
  pack.raku menu restore editors  [<message>]  [-c|--color|--colour] [-s|--syntax]

```

```
pack.raku do --help
Usage:
  pack.raku do <dir> [-f|--force]

```


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

# NAME Filetype::Magic

Try to guess a files type using the libmagic heuristic library.

# SYNOPSIS

Object oriented mode:

```
use Filetype::Magic;

my $magic = Magic.new;

say $magic.type: '/path/to/file.name';

```

Or use a convenience function.

Subroutine interface:

```
use Filetype::Magic;

say file-type '/path/to/file.name';

```

# DESCRIPTION

Provides a Raku interface to the libmagic shared library used by the 'file' utility to guess file types, installed by default on most BSDs and Linuxs. Libraries available for OSX and Windows as well.

Linux / BSD / OSX: Needs to have the shared library: libmagic-dev installed. May install the shared library directly or install the file-dev packages which will include the shared libmagic library file. Needs the header files so will need the dev packages even if you already have libmagic installed.

Windows: Needs libmagic.dll. Older 32bit packages are available on the authors site; the newest version available is 5.03. 64bit dlls can be built by following instructions on the nscaife github page (link below). At 5.29 by default, though it appears that it attempts to update to the latest version on build. (5.32 as of this writing.)

| Platform | Install Method |
| --- | --- |
| Debian derivatives | [sudo] apt-get install libmagic-dev |
| FreeBSD | [sudo] pkg install libmagic-dev |
| Fedora | [sudo] dnf install libmagic-dev |
| OSX | [sudo] brew install libmagic |
| OpenSUSE | [sudo] zypper install libmagic-dev |
| Red Hat | [sudo] yum install file-devel |
| Source Code on GitHub | https://github.com/file/file |
| Windows 32bit (older) | http://gnuwin32.sourceforge.net/packages/file.htm |
| Windows 64bit (newer) | https://github.com/nscaife/file-windows |

---

## FLAGS

There is a series of flags which control the behavior of the search:

| Flag | hex value | meaning |
| --- | --- | --- |
| MAGIC\_NONE | 0x000000, | No flags |
| MAGIC\_DEBUG | 0x000001, | Turn on debugging |
| MAGIC\_SYMLINK | 0x000002, | Follow symlinks |
| MAGIC\_COMPRESS | 0x000004, | Check inside compressed files |
| MAGIC\_DEVICES | 0x000008, | Look at the contents of devices |
| MAGIC\_MIME\_TYPE | 0x000010, | Return the MIME type |
| MAGIC\_CONTINUE | 0x000020, | Return all matches |
| MAGIC\_CHECK | 0x000040, | Print warnings to stderr |
| MAGIC\_PRESERVE\_ATIME | 0x000080, | Restore access time on exit |
| MAGIC\_RAW | 0x000100, | Don't translate unprintable chars |
| MAGIC\_ERROR | 0x000200, | Handle ENOENT etc as real errors |
| MAGIC\_MIME\_ENCODING | 0x000400, | Return the MIME encoding |
| MAGIC\_MIME | 0x000410, | MAGIC\_MIME\_TYPE +| MAGIC\_MIME\_ENCODING |
| MAGIC\_APPLE | 0x000800, | Return the Apple creator and type |
| MAGIC\_NO\_CHECK\_COMPRESS | 0x001000, | Don't check for compressed files |
| MAGIC\_NO\_CHECK\_TAR | 0x002000, | Don't check for tar files |
| MAGIC\_NO\_CHECK\_SOFT | 0x004000, | Don't check magic entries |
| MAGIC\_NO\_CHECK\_APPTYPE | 0x008000, | Don't check application |
| MAGIC\_NO\_CHECK\_ELF | 0x010000, | Don't check for elf details |
| MAGIC\_NO\_CHECK\_TEXT | 0x020000, | Don't check for text files |
| MAGIC\_NO\_CHECK\_CDF | 0x040000, | Don't check for cdf files |
| MAGIC\_NO\_CHECK\_TOKENS | 0x100000, | Don't check tokens |
| MAGIC\_NO\_CHECK\_ENCODING | 0x200000, | Don't check text encodings |

The flags may be set during construction by passing a :flags(WHATEVER) value in to the `.new( )` method, or may be adjusted later using the `.set-flags( )` method.

## FUNCTIONS - subroutine interface

Useful for one-and-done, one-off use.

```
sub file-type( IO::Path $path, Bool :$mime )
   # or
sub file-type( Str $filename, Bool :$mime )
   # or
sub file-type( IO::Handle $handle, Bool :$mime )
    # or
sub file-type( Buf $buffer, Bool :$mime )

```

Try to detect file type of a given file path/name, or open file handle, or string buffer. Strings must be in a specific encoding for the C library, so to avoid encoding issues and to differentiate string buffers from string filenames, you must pass strings as a Buf encoded appropriately. Pass a keyword parameter `mime` to get a mime type result.

--

## METHODS - object interface

For when you would like a persistent instance.

```
method new  # Default database, default flags(none)
   # or
method new( :magicfile( '/path/to/magic/database.file' ) ) # Load a custom database
   # or
method new( :flags( MAGIC_SYMLINK +| MAGIC_MIME ) ) # Adjust search/reporting behavior

```

Construct a new `Magic` instance with passed parameters if desired.

--

```
method set-flags( int32 $flags = 0 )

```

Allows modification of parameters after initialization. Numeric-bitwise `or` any parameters together.

E.G. `$magic-instance.set-flags( MAGIC_SYMLINK +| MAGIC_MIME )`.

--

```
method get-flags( )

```

Query which flags are set, returns the int32 value of the set flags.

--

```
method type( IO::Path $path )
   # or
method type( Str $filename )
   # or
method type( IO::Handle $handle )
   # or
method type( Buf $buffer )

```

Try to detect file type of a given a file path/name, or open file handle, or string buffer. Strings must be in a specific encoding for the C library, so to avoid encoding issues and to differentiate string buffers from string filenames, you must pass strings as a Buf encoded appropriately.

--

```
method version()

```

Return the current version. First digit is major version number, rest are minor.

---

There are several semi-private methods which mostly deal with initialization and setup. There is nothing preventing you from accessing them, they are publically available, but most people won't ever need to use them.

```
method magic-database( str $magic-database, int32 $flags )

```

Location of the magic database file, pass Nil to load the default database. Pass any flags numeric-bitwise `or`ed together to adjust behavior. (See `method set-flags`)

--

```
method magic-init( int32 $flags = 0 )

```

Initialize the file-magic instance, allocate a data structure to hold information and return a pointer to it. Pointer is stored in the class as $!magic-cookie.

--

```
method magic-load( Pointer $magic-struct, str $database-list )

```

Load the database file(s) into the data structure.

--

```
method magic-error()

```

Pass any errors back up to the calling code.

--

Once the Magic instance is initialized, you may query the database locations by checking the `$magic-instance.database` string. Contains the various file paths to loaded database files as a colon separated string. Do not try to change the database string directly. It will not affect the current instance; it is only a convenience method to make it easier to see the currently loaded files. Changes to the database need to be done with the `magic-load( )` method.

---

A few methods dealing with generating, compiling, and checking magic database files have yet to be implemented.

# AUTHOR

2019 Steve Schulze aka thundergnat

This package is free software and is provided "as is" without express or implied warranty. You can redistribute it and/or modify it under the same terms as Perl itself.

libmagic library and file utility v5.x author: Ian Darwin, Christos Zoulas, et al.

#### CONTRIBUTORS

github: gmoshkin

# LICENSE

Licensed under The Artistic 2.0; see LICENSE.


## unpack.md
unpack

Combined from primary sources listed below.

# [In role Blob](#___top "go to top of document")[§](#(role_Blob)_routine_unpack "direct link")

See primary documentation
[in context](/type/Blob#routine_unpack)
for **routine unpack**.

This method is considered **experimental**, in order to use it you will need to do:

```raku
use experimental :pack;

multi method unpack(Blob:D: Str:D $template)
multi method unpack(Blob:D: @template)
multi        unpack(Blob:D \blob, Str:D $template)
multi        unpack(Blob:D \blob, @template)
```

Extracts features from the blob according to the template string, and returns them as a list.

The template string consists of zero or more units that begin with an ASCII letter, and are optionally followed by a quantifier. The quantifier can be `*` (which typically stands for "use up the rest of the Blob here"), or a positive integer (without a `+`).

Whitespace between template units is ignored.

Examples of valid templates include `"A4 C n*"` and `"A*"`.

The following letters are recognized:

| Letter | Meaning |
| --- | --- |
| A | Extract a string, where each element of the Blob maps to a codepoint |
| a | Same as 'A' |
| C | Extract an element from the blob as an integer |
| H | Extracts a hex string |
| L | Extracts four elements and returns them as a single unsigned integer |
| n | Extracts two elements and combines them in "network" (BigEndian) byte order into a single integer |
| N | Extracts four elements and combines them in "network" (BigEndian) byte order into a single integer |
| S | Extracts two elements and returns them as a single unsigned integer |
| v | Same as 'S' |
| V | Same as 'L' |
| x | Drop an element from the blob (that is, ignore it) |
| Z | Same as 'A' |

Example:

```raku
use experimental :pack;
say Blob.new(1..10).unpack("C*");
# OUTPUT: «(1 2 3 4 5 6 7 8 9 10)␤»
```


## dist_cpan-TYIL-File-Zip.md
# NAME

File::Zip

# AUTHOR

Patrick Spek [p.spek@tyil.work](mailto:p.spek@tyil.work)

# VERSION

0.1.2

# Description

A wrapper around zip files, using zip/unzip commands

# Installation

Install this module through [zef](https://github.com/ugexe/zef):

```
zef install File::Zip

```

# License

This module is distributed under the terms of the AGPL-3.0.


## dist_cpan-WBIKER-Module2Rpm.md
# NAME

App::Module2Rpm

# SYNOPSIS

```
# Download the source of a Raku module, write the spec file and upload them to OBS.
module2rpm --module=Module::Name

# Download the source, write the spec file and upload them to OBS for each line in a file.
module2rm --file=filePath

```

# DESCRIPTION

This program downloads the source of a given Raku module, writes the spec file with the module
metadata and uploaded them to Open Build Service (OBS).
There are two commandline parameter:

* `--module=Module::Name` Looks for the metadata of the given name to find the
  source download url and metadata.
* `--file=FilePath` Handles each line in the file as either module name or metadata
  download url.

# AUTHOR

wbiker [wbiker@gmx.at](mailto:wbiker@gmx.at)


## dist_github-MadcapJake-Acme-Mangle.md
```
mangle "Hello from the other side. I must've called a thousand times."

```

### Thanks

[yoleaux](http://dpk.io/yoleaux)'s `.mangle` command

Jean-Yves Lefort's [libtranslate](http://www.nongnu.org/libtranslate/)


## dist_zef-jonathanstowe-Ikoko.md
# Ikoko

Simple Read-Only interface to the AWS Secrets Manager

[![CI](https://github.com/jonathanstowe/Ikoko/actions/workflows/main.yml/badge.svg)](https://github.com/jonathanstowe/Ikoko/actions/workflows/main.yml)

## Synopsis

```
use Ikoko;
use Kivuli;

# Using Kivuli to get session credentials for a role in EC2
# The access-key-id and secret-access-key could come from configuration
my $k = Kivuli.new;

my $ikoko = Ikoko.new(region => 'eu-west-2', access-key-id => $k.access-key-id, secret-access-key => $k.secret-access-key, token => $k.token );

say $ikoko.get-secret-value("db-user").secret-string;

```

## Description

This provides a simple interface to the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/index.html). The secrets manager enables an application to retrieve a secret credential (for, say, an RDS database ) at run time without having to save it in your application configuration.

If used with [Kivuli](https://docs.aws.amazon.com/secretsmanager/index.html) in an EC2 or Elasticbeanstalk instance you can avoid having all credentials in the configuration or application code. When used with the temporary credentials as supplied by Kivuli the `token` must be provided. If you are using a permanent access key for
an account then the `token` is optional.

For this to work the account or IAM role must have permission to retrieve the secrets, which is described [here](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access.html).

Currently this only implements `GetSecretValue` as this is most useful for an application.

## Installation

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

```
 zef install Ikoko

```

## Support

This currently only implements the bare essentials for my needs, if you need some other features or have other suggestions or patches please raise an issue on [Github](https://github.com/jonathanstowe/Ikoko/issues) and I'll see what I can do.

Although the unit tests are rather thin, rest assured that I have tested this manually and is being used in the project I wrote it for.

## Licence & Copyright.

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

© Jonathan Stowe 2021


## dist_zef-guifa-DateTime-React.md
# DateTime::React

A module for Raku that makes it incredibly easy to be alerted when clock rollovers occur (e.g. when the minute or hour ticks up).

Using it is very simple:

```
use DateTime::React;

react {
    whenever minute-shifts {
        say "We've gone from ??:??:59 to ??:??:00!";
    }
    whenever hour-shifts {
        say "We've gone from ??:59:59 to to ??:00:00!";
    }
    whenever day-shifts {
        say "We've gone from 23:59:59 to to 00:00:00!";
    }
    whenever timezone-shifts -> $shift {
        say "The offset in {$shift.timezone} is now {$shift.new-offset}!";
    }
}

```

Other time options presently include `month-shifts` and `year-shifts` (these are pegged to the Gregorian calendar).

Each supply emits a meta event of type `DateTimeEventish`. It provides three values:

* **`time`**: the time the event was scheduled
* **`next-at`**: when the next event will occur
* **`type`**: the type of event (any of *minute, hour, day, month, year, timezone*)

Currently, only `timezone-shifts()` provides additional metadata:

* **`olson-id`**: the Olson (or IANA) identifier for the timezone
* **`timezone`**: an alias of `olson-id`
* **`old-offset`**: the former GMT offset (e.g. -5h for *America/New\_York* for spring switch over)
* **`new-offset`**: the now current GMT offset (e.g. -4h for *America/New\_York* for spring switch over)

When using `timezone-shifts()`, this module will (currently) automatically adjust the `$*TZ` value for you so that new DateTime objects are generated with the correct offset.
Be mindful that DateTime itself is not timezone aware, so creating historical/future dates will always use the current $\*TZ value.
If that is needed, you should look at the `DateTime::Timezones` module which does that for you.

The `$*TZ` adjusting feature may be moved into a different module down the road but the behavior will be maintained (at the cost of an additional dependency for this one).

# Version history

* **v0.2.0**
  * Now using terms to avoid parentheses for teh pretty
* **v0.1.1**
  * Switched to live supplies internally for improved reliability
* **v0.1.0**
  * Initial release

# Copyright / License

Copyright © 2022 Matthew Stephen Stuckwisch. Licensed under the Artistic License 2.0


## dist_cpan-JNTHN-LEB128.md
# LEB128

[LEB128 or Little Endian Base 128](https://en.wikipedia.org/wiki/LEB128)
is a variable-length encoding of integers - that is, it aims to store
integers of different sizes efficiently. It is used in the DWARF debug
information format, Web Assembly, and other formats and protocols. This
Raku module provides both encoding and decoding.

## Encoding

There are both signed and unsigned encoding functions, `encode-leb128-signed`
and `encode-leb128-unsigned` respectively. Both are `multi`s with candidates
that take an `Int` and return a `Buf` with the encoded value:

```
my $buf-eu = encode-leb128-unsigned(1234);
my $buf-es = encode-leb128-signed(-1234);

```

Or to write the encoded `Int` into a `Buf` and return the number of bytes
written, which is often more efficient since it avoids the creation of a
temporary `Buf`:

```
my $buf = Buf.new;
my $offset = 0;
$offset += encode-leb128-unsigned(1234, $buf, $offset);

```

## Decoding

There are both signed and unsigned decoding functions, `decode-leb128-signed`
and `decode-leb128-unsigned` respectively. Both are `multi`s with candidates
that take a `Buf` and try to decode an `Int` from the start of it, returning
that `Int`:

```
my $value-du = decode-leb128-unsigned($entire-buffer-u);
my $value-ds = decode-leb128-signed($entire-buffer-s);

```

Or that decode the value from a specified offset in a given buffer, and use
an `rw` parameter of type `int`, which is incremented by the number of bytes
consumed.

```
my int $read;
my $value = decode-leb128-unsigned($buffer, $offset, $read);

```

To have the offset updated, it may be passed as both parameters:

```
my $value = decode-leb128-unsigned($buffer, $offset, $offset);

```


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

# NAME

paths - A fast recursive file / directory finder

# SYNOPSIS

```
use paths;

.say for paths;                             # all files from current directory

.say for paths($dir);                       # all files from $dir

.say for paths(:dir(* eq '.git'));          # files in ".git" directories

.say for paths(:file(*.ends-with(".json");  # all .json files

.say for paths(:recurse);                   # also recurse in non-accepted dirs

.say for paths(:follow-symlinks);           # also recurse into symlinked dirs

.say for paths(:!file);                     # only produce directory paths

say is-regular-file('/etc/passwed');        # True (on Unixes)
)
```

# DESCRIPTION

By default exports two subroutines: `paths` (returning a `Seq` of absolute path strings of files (or directories) for the given directory and all its sub-directories (with the notable exception of `.` and `..`).

And `is-regular-file`, which returns a `Bool` indicating whether the given absolute path is a regular file.

# SELECTIVE IMPORTING

```
use paths <paths>;  # only export sub paths

```

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

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

```
use path <paths:find-all-paths>;  # export "path-exists" as "alive"

.say for find-all-paths;

```

# EXPORTED SUBROUTINES

## paths

The `paths` subroutine returns a `Seq` of absolute path strings of files for the given directory and all its sub-directories (with the notable exception of `.` and `..`).

### ARGUMENTS

* directory

The only positional argument is optional: it can either be a path as a string or as an `IO` object. It defaults to the current directory (also when an undefined value is specified. The (implicitely) specified directory will **always** be investigated, even if the directory name does not match the `:dir` argument.

If the specified path exists, but is not a directory, then only that path will be produced if the file-matcher accepts the path. In all other cases, an empty `Seq` will be returned.

* :dir

The named argument `:dir` accepts a matcher to be used in smart-matching with the basename of the directories being found. If accepted, will produce both files as well as other directories to recurse into.

It defaults to skipping all of the directories that start with a period (also if an undefined value is specified).

* :file

The named argument `:file` accepts a matcher to be used in smart-matching with the basename of the file being found. It defaults to `True`, meaning that all possible files will be produced (also if an undefined values is specified).

If the boolean value `False` is specified, then **only** the paths of directories will be produced.

* :recurse

Flag. The named argument `:recurse` accepts a boolean value to indicate whether subdirectories that did **not** match the `:dir` specification, should be investigated as well for other **directories** to recurse into. No files will be produced from a directory that didn't match the `:dir` argument.

By default, it will not recurse into directories.

* :follow-symlinks

The named argument `:follow-symlinks` accepts a boolean value to indicate whether subdirectories, that are actually symbolic links to a directory, should be investigated as well. By default, it will not.

## is-regular-file

```
say is-regular-file('/etc/passwed');  # True (on Unixes)

```

Returns a `Bool` indicating whether the given absolute path is a regular file.

# AUTHOR

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

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

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


## dist_cpan-LEONT-Actor.md
[![Build Status](https://travis-ci.org/Leont/raku-actor.svg?branch=master)](https://travis-ci.org/Leont/raku-actor)

# NAME

Actor - an actor model threading library

# SYNOPSIS

```
use v6.d;
use Actor;

my $actor = spawn {
    receive-loop
        -> Str $message, Actor::Handle $other {
            say "Message $message";
            $other.send($message);
        },
        -> Int :$number, Str :$message {
            say "Message $message" if $number %% 7;
        },
        -> "stop" {
            last;
        };
}

$actor.send("message", self-handle);
receive
    -> Str $message {
        $actor.send(:42number, :$message);
        $actor.send("stop");
    };

await $actor;

```

# DESCRIPTION

Actor is a module that implements actor model threading for Raku.

actors are …

# INTERFACE

## module Actor

### spawn(&starter, \*@args, Bool :$monitored --> Handle:D)

This starts a new actor that calls `&starter` with `@args` as its arguments, and returns a handle to that actor. If `$monitored` is true, it will also set up a monitor from the new actor to the current one.

### receive(\*@handlers --> Nil)

This will loop through the messages in the queue, and for each message will try to match it in turn to each of the `@handlers` passed to it. If it matches it is taken from the queue and the handler is called with it. Then `receive` returns.

If no such matching message exists, it will wait for a new message to arrive that does match a handler, pushing any non-matching messages to the queue.

### receive-loop(\*@handlers --> Nil)

This will call receive in a loop with the given handlers, until one of the handlers calls `last`.

### self-handle(--> Handle:D)

This returns a handle to the current actor.

## class Actor::Handle

This class represents a handle to an actor

### send(|message --> Nil)

This will send `|message` to that actor.

### alive(--> Bool:D)

This returns true if the actor is still alive.

### add-monitor(handle = self-handle --> Handle::MonitorId)

This sets up a monitor relationship from the invocant handle to the one passed to `add-monitor` (defaulting to the current handle)

### remove-monitor(Handle::MonitorId $monitor)

This removes a monitor from the monitor list of this actor.

## monitors

Monitors are watchers on an actor's status. If the actor ends successfully, a message like this is sent:

```
(Actor::Exit, $handle, $return-value)

```

If it dies in an exception, the follow message is sent to the monitoring actor instead.

```
(Actor::Error, $handle, $exception)

```

# AUTHOR

Leon Timmermans [fawaka@gmail.com](mailto:fawaka@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2020 Leon Timmermans

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


## dist_cpan-RONALDWS-US-ASCII.md
# NAME

US-ASCII - ASCII restricted character classes based on Perl 6 predefined classes and ABNF/RFC5234 Core.

[![Build Status](https://travis-ci.org/ronaldxs/Perl6-US-ASCII.png)](https://travis-ci.org/ronaldxs/Perl6-US-ASCII)
[![Build status](https://ci.appveyor.com/api/projects/status/github/ronaldxs/Perl6-US-ASCII?svg=true)](https://ci.appveyor.com/project/ronaldxs/Perl6-US-ASCII/branch/master)

# SYNOPSIS

```
use US-ASCII;

say so /<US-ASCII::alpha>/ for <A À 9>; # True, False, False

grammar IPv6 does US-ASCII-UC {
    token h16 { <HEXDIG> ** 1..4}
}
# False, True, True, False, False
say so IPv6.parse($_, :rule<h16>) for ('DÉÃD', 'BEEF', 'A0', 'A๐', 'a0');

grammar SQL_92 does US-ASCII-UC {
    token unsigned-integer { <DIGIT>+ }
}
# True, False
say so SQL_92.parse($_, :rule<unsigned-integer>) for ('42', '4૫');

```

```
use US-ASCII :UC;

say so /<ALPHA>/ for <A À 9>; # True, False, False

```

# DESCRIPTION

This module provides regex character classes restricted to ASCII including the predefined character classes of Perl 6 and ABNF (RFC 5234) Core rules. The US-ASCII grammar defines most character classes in lower case for direct use without composition as in the first SYNOPSIS example. The US-ASCII-UC role defines all character classes in upper case and is intended for composition into grammars. Upper case US-ASCII tokens may be imported with the import tag `:UC`. Composition of upper case named regex/tokens does not override the predefined Perl 6 character classes and conforms better to RFC 5234 ABNF, facilitating use with grammars of other internet standards based on that RFC.

The distribution also includes an `US-ASCII::ABNF::Core` module with tokens for ABNF Core as enumerated in RFC 5234. See further details in that module's documentation. There is also an `US-ASCIIx` module which is a POSIX variant with a `:POSIX` import tag and `alpha`, `alnum` and their uppercase export versions do not include underscore, '\_'.

The `US-ASCII-ABNF` role of the `US-ASCII` module extends `US-ASCII-UC` by defining all ABNF Core tokens including ones like DQUOTE that are trivially coded in Perl6 and others that are likely only to be useful for composition in grammars related to ABNF. For conformance with ABNF, `ALPHA` and `ALNUM` do not include underscore, '\_' in this module.

Unlike RFC 5234, and some existing Perl 6 implementations of it, US-ASCII rules are very rarely defined by ordinal values and mostly use, hopefully clearer, Perl 6 character ranges and names. Actually you could code most of these rules/tokens easily enough yourself as demonstrated below but the modules may still help collect and organize them for reuse.

```
my token DIGIT { <digit> & <:ascii> } # implemented with conjunction

```

# Named Regex (token)

## Named Regex (token) in differing case in US-ASCII and US-ASCII-UC/(import tag :UC)

Almost all are based on predefined Perl 6 character classes.

* alpha / ALPHA
* alpha\_x / ALPHAx # alpha without '\_' underscore
* upper / UPPER
* lower / LOWER
* digit / DIGIT
* xdigit / XDIGIT
* hexdig / HEXDIG # ABNF 0..9A..F (but not a..f)
* alnum / ALNUM
* alnum\_x / ALNUMx # alnum without '\_' underscore
* punct / PUNCT
* graph / GRAPH
* blank / BLANK
* space / SPACE
* print / PRINT
* cntrl / CNTRL
* vchar / VCHAR # ABNF \x[21]..\x[7E] visible (printing) chars
* wb / WB
* ww / WW
* ident / IDENT

## Shared by both US-ASCII and US-ASCII-UC

* BIT ('0' or '1')
* CHAR (Anything in US-ASCII other than NUL)
* CRLF

## Named Regex (token) in US-ASCII-ABNF/(import tag :ABNF) only useful for ABNF

* CR
* CTL
* DQUOTE
* HTAB
* LF
* SP (space)
* LWSP (ABNF linear white space)
* OCTET
* WSP

| ABNF Core rule | Perl 6 equivalent |
| --- | --- |
| CR | \c[CR] |
| CTL | US-ASCII cntrl / CNTRL |
| DQUOTE | '"' |
| HTAB | "\t" |
| LF | \c[LF] |
| SP | ' ' |
| WSP | US-ASCII blank / BLANK |

## US-ASCIIx import tag :POSIX

As previously mentioned for the `US-ASCII` module `ALPHA` and `ALNUM` include the underscore ('\_') and for `US-ASCIIx` those two tokens DO NOT include underscore.

* ALPHA
* UPPER
* LOWER
* DIGIT
* XDIGIT
* ALNUM
* PUNCT
* GRAPH
* BLANK
* SPACE
* PRINT
* CNTRL

# ABNF Core

Since ABNF is defined using the ASCII character set the distribution includes an US-ASCII::ABNF::Core module defining the tokens for ABNF Core as enumerated in RFC 5234. See that module's documentation for more detail.

# Backward compatibility break with CR, LF, SP.

In 0.1.X releases CR, LF and SP were provided by the US-ASCII grammar. They are now treated as ABNF Core only tokens, as they can be easily enough coded in Perl 6 using equivalents noted in the table above.

# LIMITATIONS

Perl 6 strings treat `"\c[CR]\c[LF]"` as a single grapheme and that sequence will not match either `<CR>` or `<LF>` but will match `<CRLF>`.

The Unicode `\c[KELVIN SIGN]` at code point `\x[212A]` is normalized by Perl 6 string processing to the letter 'K' and `say so "\x[212A]" ~~ /K/` prints `True`. Regex tests that match the letter K, including US-ASCII tokens, may thus appear to match the Kelvin sign.

# Export of tokens

Export of tokens and other `Regex` types is not formally documented. Regex(es) are derived from `Method` which is in turn derived from `Routine`. `Sub` is also derived from `Routine` and well documented and established as exportable including lexical `my sub`. There is a roast example of exporting an operator method in S06-operator-overloading/infix.t and also mention of method export in a Dec 12, 2009 advent blog post. Further documentation and test of export on `Method` and `Regex` types is of interest to these modules and project.

This implementation uses `my`/lexical scope to export tokens the same way a module would export a `my sub`. I looked into `our` scope and no scope specifier for the declarations and came across [roast issue #426](https://github.com/perl6/roast/issues/426), which I felt made the choice ambiguous and export of `my token` currently the best of the three.


## ast.md
ast

Combined from primary sources listed below.

# [In Match](#___top "go to top of document")[§](#(Match)_method_ast "direct link")

See primary documentation
[in context](/type/Match#method_ast)
for **method ast**.

Alias for [method made](#method_made).


## method.md
class Method

Member function

```raku
class Method is Routine { }
```

A type for methods that behaves in the same way as [`Routine`](/type/Routine) with some exceptions listed below. For details of a method's parameter list see [`Signature`](/type/Signature).

To create a method outside a [class definition](/language/typesystem#Methods), use the declarators `my` and `method`. If an [identifier](/language/syntax#Identifiers) is provided the methods name will be injected into the scope specified by the declarator.

```raku
my $m = method ($invocant: $param) {
    say "$invocant: '$param'";
}
"greeting".$m("hello");  # OUTPUT: «greeting: 'hello'␤»

<a b c>.&(my method (List:D:) { say self.raku; self }).say;
# OUTPUT: «("a", "b", "c")␤(a b c)␤»
```

The invocant of a method defaults to `self`. A type constraint including a type-smiley can be used and is honored both for methods defined in a class and for free floating methods. Call the latter with `.&` on an object.

```raku
my method m(Int:D: $b){
    say self.^name
}
my $i = 1;
$i.&m(<a>);
# OUTPUT: «Int␤»
```

Please note that the main difference between methods defined within and without a class is the need to use `&` to invoke them in the latter case. In case any other sigil is used in the definition, as in the first example, that sigil can also be used.

Methods automatically capture extra named arguments into the special variable `%_`, where other types of [`Routine`](/type/Routine) will throw at runtime. So

```raku
method x() {}
```

is actually equivalent to

```raku
method x(*%_) {}
```

Extra arguments will be forwarded by [`nextsame` and friends](/language/functions#Re-dispatching).

```raku
class A {
    multi method m(:$a, :$b) { say "2 named" }
}

class B is A {
    method m(:$a) { say "1 named"; nextsame }
}
B.m( :1a, :2b );
# OUTPUT: «1 named␤2 named␤»
```

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

Type relations for `Method`

raku-type-graph

Method
Method

Routine
Routine

Method->Routine

Mu
Mu

Any
Any

Any->Mu

Callable
Callable

Code
Code

Code->Any

Code->Callable

Block
Block

Block->Code

Routine->Block

Regex
Regex

Regex->Method

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


## dist_github-mj41-Algorithm-SpiralMatrix.md
# Algorithm::SpiralMatrix

Various Raku Sequences for spirals in matrix (two-dimensional
arrays).

For overview see <docs/test-output.md>
and <docs/distance-variants.md>.

## Synopsis

```
use Algorithm::SpiralMatrix;

my $i = 1;
for square_distance(order => 'clockwise') -> ($x,$y) {
    say "{$i++} $x,$y";
    last if $i > 25;
}

```

will print

```
1 0,0
2 0,-1
3 1,0
4 0,1
5 -1,0
6 1,-1
8 -1,1
9 -1,-1
...
24 -2,2
25 -2,-2

```

## Description

This module provides implementation of algorithms to generate various
spiral sequences in matrix (two-dimensional array).

## Related links

* [zero2cx/spiral-matrix](https://github.com/zero2cx/spiral-matrix) (Python)
* [bangjunyoung/SpiralMatrixSharp](https://github.com/bangjunyoung/SpiralMatrixSharp) (F#)
* [Exercism: spiral-matrix](https://github.com/exercism/problem-specifications/blob/master/exercises/spiral-matrix/description.md)

## Installation

Rakudo Raku distribution contains *zef*. Use

```
zef install Algorithm::SpiralMatrix

```

If you have a local copy of this repository use

```
zef install .

```

in the module directory.

## Support

Feel free to share your suggestions, patches or comment
<https://github.com/mj41/Algorithm-SpiralMatrix/issues>.

## Licence and Copyright

This is free software. Please see the [LICENCE file](LICENSE).

© Michal Jurosz, 2019


## dist_zef-jforget-Date-Calendar-FrenchRevolutionary.md
# NAME

Date::Calendar::FrenchRevolutionary - Conversions from / to the French Revolutionary calendar

# SYNOPSIS

Converting a Gregorian date (e.g. 9th November 1799) into French
Revolutionary (18 Brumaire VIII).

```
use Date::Calendar::FrenchRevolutionary;
my Date                                $Bonaparte's-coup-gr;
my Date::Calendar::FrenchRevolutionary $Bonaparte's-coup-fr;

$Bonaparte's-coup-gr .= new(1799, 11, 9);
$Bonaparte's-coup-fr .= new-from-date($Bonaparte's-coup-gr);
say $Bonaparte's-coup-fr.strftime("%A %e %B %Y");

```

Converting a French Revolutionary date (e.g. 9th Thermidor II) to
Gregorian (which gives 27th July 1794).

```
use Date::Calendar::FrenchRevolutionary;
my Date::Calendar::FrenchRevolutionary $Robespierre's-downfall-fr;
my Date                                $Robespierre's-downfall-gr;

$Robespierre's-downfall-fr .= new(year    =>  2
                                , month   => 11
                                , day     =>  9);
$Robespierre's-downfall-gr =  $Robespierre's-downfall-fr.to-date;
say $Robespierre's-downfall-gr;

```

# INSTALLATION

```
zef install Date::Calendar::FrenchRevolutionary

```

or

```
git clone https://github.com/jforget/raku-Date-Calendar-FrenchRevolutionary.git
cd raku-Date-Calendar-FrenchRevolutionary
zef install .

```

# DESCRIPTION

Date::Calendar::FrenchRevolutionary is a class representing dates in
the French Revolutionary calendar. It allows you to convert a
Gregorian date into a French Revolutionary date or the other way.

The Revolutionary calendar was in use in France from 24 November 1793
(4 Frimaire II) to 31 December 1805 (10 Nivôse XIV). The modules in
this distribution extend the calendar to the present and to a few
centuries in the future, not limiting to Gregorian year 1805.

This new calendar was an attempt to apply the decimal rule (the basis
of the metric system) to the calendar. Therefore, the week
disappeared, replaced by the décade, a 10-day period. In addition, all
months have exactly 3 décades, no more, no less.

Since 12 months of 30 days each do not make a full year (365.24 days),
there are 5 or 6 additional days at the end of a year. These days are
called "Sans-culottides", named after a political faction, but we
often find the phrase "jours complémentaires" (additional days). These
days do not belong to any month, but for programming purposes, it is
convenient to consider they form a 13th month.

At first, the year was beginning on the equinox of autumn, for two
reasons. First, the republic had been established on 22 September
1792, which happened to be the equinox, and second, the equinox was
the symbol of equality, the day and the night lasting exactly 12 hours
each. It was therefore in tune with the republic's motto "Liberty,
Equality, Fraternity". But it was not practical, so Romme proposed a
leap year rule similar to the Gregorian calendar rule.

The distribution contains two other classes, one where there was no
reform and the automn equinox rule stayed in effect, another where the
arithmetic rule was established since the beginning of the calendar.

# AUTHOR

Jean Forget

# COPYRIGHT AND LICENSE

Copyright (c) 2019, 2020, 2024 Jean Forget, all rights reserved

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


## dist_cpan-TITSUKI-MeCab.md
[![Build Status](https://travis-ci.org/titsuki/raku-MeCab.svg?branch=master)](https://travis-ci.org/titsuki/raku-MeCab)

# NAME

MeCab - A Raku bindings for libmecab ( <http://taku910.github.io/mecab/> )

# SYNOPSIS

## EXAMPLE 1

```
use MeCab;
use MeCab::Tagger;

my Str $text = "すもももももももものうち。";
my $mecab-tagger = MeCab::Tagger.new('-C');
loop ( my MeCab::Node $node = $mecab-tagger.parse-tonode($text); $node; $node = $node.next ) {
       say ($node.surface, $node.feature).join("\t");
}

# OUTPUT«
#         BOS/EOS,*,*,*,*,*,*,*,*
# すもも  名詞,一般,*,*,*,*,すもも,スモモ,スモモ
# も      助詞,係助詞,*,*,*,*,も,モ,モ
# もも    名詞,一般,*,*,*,*,もも,モモ,モモ
# も      助詞,係助詞,*,*,*,*,も,モ,モ
# もも    名詞,一般,*,*,*,*,もも,モモ,モモ
# の      助詞,連体化,*,*,*,*,の,ノ,ノ
# うち    名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
# 。      記号,句点,*,*,*,*,。,。,。
#         BOS/EOS,*,*,*,*,*,*,*,*
# »

```

## EXAMPLE 2

```
use MeCab;
use MeCab::Lattice;
use MeCab::Tagger;
use MeCab::Model;

my MeCab::Model $model .= new;
my MeCab::Tagger $tagger = $model.create-tagger;
my MeCab::Lattice $lattice = $model.create-lattice;
$lattice.add-request-type(MECAB_NBEST);
$lattice.sentence("今日も");

if $tagger.parse($lattice) {
   say $lattice.nbest-tostr(2);
}

# OUTPUT«
# 今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
# も      助詞,係助詞,*,*,*,*,も,モ,モ
# EOS
# 今日    名詞,副詞可能,*,*,*,*,今日,コンニチ,コンニチ
# も      助詞,係助詞,*,*,*,*,も,モ,モ
# EOS
# »

```

# DESCRIPTION

MeCab is a Raku bindings for libmecab ( <http://taku910.github.io/mecab/> ).

# NOTICE

## COMPATIBILITY

MeCab currently doesn't support Windows. It supports Linux/Unix or Mac OS X.

## BUILDING MeCab

MeCab depends on the following:

* wget
* mecab-0.996
* mecab-ipadic-2.7.0-20070801

Once the build starts, it automatically downloads `mecab-0.996` and `mecab-ipadic-2.7.0-20070801` with `wget` and installs these stuffs under the `$HOME/.p6mecab` directory, where `$HOME` is your home directory.

# Use 3rd-party dictionary

## mecab-ipadic-neologd

* Step1: download and install neologd

Example:

```
$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ export PATH=$HOME/.p6mecab/bin:$PATH
$ ./bin/install-mecab-ipadic-neologd -p $HOME/.p6mecab/lib/mecab/dic/ipadic-neologd

```

* Step2: Use .new(:dicdir(PATH\_TO\_THE\_DIR))

Example:

```
use MeCab;
use MeCab::Tagger;

my Str $text = "トランプ大統領 ワシントンで大規模軍事パレードを指示";
my $mecab-tagger = MeCab::Tagger.new(:dicdir("$*HOME/.p6mecab/lib/mecab/dic/ipadic-neologd"));
loop ( my MeCab::Node $node = $mecab-tagger.parse-tonode($text); $node; $node = $node.next ) {
       say ($node.surface, $node.feature).join("\t");
}

# OUTPUT«
#         BOS/EOS,*,*,*,*,*,*,*,*
# トランプ大統領  名詞,固有名詞,人名,一般,*,*,ドナルド・トランプ,トランプダイトウリョウ,トランプダイトウリョー
# ワシントン      名詞,固有名詞,地域,一般,*,*,ワシントン,ワシントン,ワシントン
# で      助詞,格助詞,一般,*,*,*,で,デ,デ
# 大規模  名詞,一般,*,*,*,*,大規模,ダイキボ,ダイキボ
# 軍事パレード    名詞,固有名詞,一般,*,*,*,軍事パレード,グンジパレード,グンジパレード
# を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
# 指示    名詞,サ変接続,*,*,*,*,指示,シジ,シジ
#         BOS/EOS,*,*,*,*,*,*,*,*
# »

```

# AUTHOR

titsuki [titsuki@cpan.org](mailto:titsuki@cpan.org)

# COPYRIGHT AND LICENSE

Copyright 2016 titsuki

libmecab ( <http://taku910.github.io/mecab/> ) by Taku Kudo is licensed under the GPL, LGPL or BSD Licenses.

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


## dist_zef-renormalist-Data-DPath.md
[![Actions Status](https://github.com/renormalist/raku-Data-DPath/actions/workflows/test.yml/badge.svg)](https://github.com/renormalist/raku-Data-DPath/actions)

# NAME

Data::DPath - DPath is not XPath!

# SYNOPSIS

```
use Data::DPath;

```

# DESCRIPTION

Data::DPath is a re-implementation of the Perl module *Data::DPath*.

WATCH OUT: The early versions are ONLY to get the Raku/Zef/Github infrastructure working, there is no real code yet. If you read this sentence then this module is in its early stages of development and should not be used in any way except for contributing.

# AUTHOR

Steffen Schwigon [ss5@renormalist.net](mailto:ss5@renormalist.net)

# COPYRIGHT AND LICENSE

Copyright 2024 Steffen Schwigon

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

# CAVEATS

This module is not a 1:1 port of the Perl version. So there is potential for subtly different behaviour.

## Different dpath parsing

First of all, it utilizes grammars for the DPaths instead of Text::Balanced. This means it could miss dpath constructs that worked before just because of Text::Balanced. Please report them so the grammar can be extended.

## Different code

Besides the already discussed dpath parsing the remaining code will start out as port from Perl but will be evolve independently. It's quite possible that this eventually means a different feature set.

## Different filter expressions

In the Perl version filter expressions were actually Perl expressions, protected by *Safe.pm*. Here another expression language will be used, not sure yet, what exactly, but obviously not Perl.

## Feature differences

The Perl version provides some Perl-specific features, e.g. references into a data structure. It is not yet clear how these will work out in Raku.


## dist_zef-FRITH-Math-Libgsl-Eigensystem.md
[![Actions Status](https://github.com/frithnanth/raku-Math-Libgsl-Eigensystem/workflows/test/badge.svg)](https://github.com/frithnanth/raku-Math-Libgsl-Eigensystem/actions)

# NAME

Math::Libgsl::Eigensystem - An interface to libgsl, the Gnu Scientific Library - Eigensystems

# SYNOPSIS

```
use Math::Libgsl::Matrix;
use Math::Libgsl::Eigensystem;

my Math::Libgsl::Eigensystem::RealSymm $e .= new: 2;

my Math::Libgsl::Matrix $vm .= new: 2, 2;
$vm[0;0] = 2; $vm[0;1] = 1;
$vm[1;0] = 1; $vm[1;1] = 2

my ($eval) = $e.compute($vm);
put $eval[^2];

```

# DESCRIPTION

Math::Libgsl::Eigensystem is an interface to the Eigensystem functions of libgsl, the Gnu Scientific Library.

This module exports six classes:

* Math::Libgsl::Eigensystem::RealSymm
* Math::Libgsl::Eigensystem::ComplexHerm
* Math::Libgsl::Eigensystem::RealNonSymm
* Math::Libgsl::Eigensystem::RealGenSymm
* Math::Libgsl::Eigensystem::ComplexGenHerm
* Math::Libgsl::Eigensystem::RealGenNonSymm

each encapsulates the methods and the buffers needed to create and compute the eigenvalues and the eigenvectors of different kind of matrices.

All these classes share the same constructor schema:

### multi method new(Int $size!, Bool $vectors?)

### multi method new(Int :$size!, Bool :$vectors?)

The constructor accepts two simple or named arguments: the size of the system we want to compute and the request to compute the eigenvectors besides the eigenvalues.

All the classes have a **compute** method; they differ for the number and type of arguments and the return value(s).

## Math::Libgsl::Eigensystem::RealSymm

This class acts on a real symmetrix matrix.

### method compute(Math::Libgsl::Matrix $A where .matrix.size1 == .matrix.size2, gsl\_eigen\_sort\_t :$sort --> List)

This method computes the eigenvalues and the eigenvectors, if selected during the initialization. The optional named argument **:$sort** specifies the required sort order. The symbolic names for this argument are listed in the **Math::Libgsl::Constants** module as follows:

* **GSL\_EIGEN\_SORT\_VAL\_ASC**: ascending order in numerical value
* **GSL\_EIGEN\_SORT\_VAL\_DESC**: descending order in numerical value
* **GSL\_EIGEN\_SORT\_ABS\_ASC**: ascending order in magnitude
* **GSL\_EIGEN\_SORT\_ABS\_DESC**: descending order in magnitude

This method outputs a List of values: a single **Math::Libgsl::Vector**, which contains the eigenvalues, and an optional **Math::Libgsl::Matrix**, which contains the eigenvectors if they were requested.

## Math::Libgsl::Eigensystem::ComplexHerm

This class acts on a complex hermitian matrix.

### method compute(Math::Libgsl::Matrix::Complex64 $A where .matrix.size1 == .matrix.size2, gsl\_eigen\_sort\_t :$sort --> List)

This method computes the eigenvalues and the eigenvectors, if selected during the initialization. The optional named argument **:$sort** specifies the required sort order.

This method outputs a List of values: a single **Math::Libgsl::Vector**, which contains the eigenvalues, and an optional **Math::Libgsl::Matrix::Complex64**, which contains the eigenvectors if they were requested.

## Math::Libgsl::Eigensystem::RealNonSymm

This class acts on a complex hermitian matrix.

### method compute(Math::Libgsl::Matrix $A where .matrix.size1 == .matrix.size2, Bool :$balance = False, gsl\_eigen\_sort\_t :$sort, Bool :$schur-vectors = False, Bool :$schur = False --> List)

This method computes the eigenvalues and the eigenvectors, if selected during the initialization. The optional named argument **:$balance** requires that a balancing transformation is applied to the matrix prior to computing eigenvalues. The optional named argument **:$schur** requires that it computes the full Schur form T. The optional named argument **:$schur-vectors** requires that it also computes the Schur vectors. The optional named argument **:$sort** specifies the required sort order.

This method outputs a List of values: a single **Math::Libgsl::Vector::Complex64**, which contains the eigenvalues, an optional **Math::Libgsl::Matrix::Complex64**, which contains the eigenvectors if they were requested, and an optional **Math::Libgsl::Matrix** if the Schur vectors were requested.

## Math::Libgsl::Eigensystem::RealGenSymm

### method compute(Math::Libgsl::Matrix $A where .matrix.size1 == .matrix.size2, Math::Libgsl::Matrix $B where .matrix.size1 == .matrix.size2 && .matrix.size1 == $A.matrix.size1, gsl\_eigen\_sort\_t :$sort --> List)

This method computes the eigenvalues and the eigenvectors, if selected during the initialization. It requires two mandatory **Math::Libgsl::Matrix** objects (refer to the very good C Library documentation for the meaning of those two matrices and the computation details). The optional named argument **:$sort** specifies the required sort order.

This method outputs a List of values: a single **Math::Libgsl::Vector**, which contains the eigenvalues, an optional **Math::Libgsl::Matrix**, which contains the eigenvectors if they were requested. On exit the first matrix **$A** is destroyed and the second one **$B** will contain the Cholesky decomposition of the eigenvector matrix.

## Math::Libgsl::Eigensystem::ComplexGenHerm

### method compute(Math::Libgsl::Matrix::Complex64 $A where .matrix.size1 == .matrix.size2, Math::Libgsl::Matrix::Complex64 $B where .matrix.size1 == .matrix.size2 && .matrix.size1 == $A.matrix.size1, gsl\_eigen\_sort\_t :$sort --> List)

This method computes the eigenvalues and the eigenvectors, if selected during the initialization. It requires two mandatory **Math::Libgsl::Matrix::Complex64** objects (refer to the very good C Library documentation for the meaning of those two matrices and the details of the computation). The optional named argument **:$sort** specifies the required sort order.

This method outputs a List of values: a single **Math::Libgsl::Vector**, which contains the eigenvalues, an optional **Math::Libgsl::Matrix::Complex64**, which contains the eigenvectors if they were requested. On exit the first matrix **$A** is destroyed and the second one **$B** will contain the Cholesky decomposition of the eigenvector matrix.

## Math::Libgsl::Eigensystem::RealGenNonSymm

### method compute(Math::Libgsl::Matrix $A where .matrix.size1 == .matrix.size2, Math::Libgsl::Matrix $B where .matrix.size1 == .matrix.size2 && .matrix.size1 == $A.matrix.size1, Bool :$schur-S = False, Bool :$schur-T = False, Bool :$balance = False, Bool :$schur-vectors = False, gsl\_eigen\_sort\_t :$sort --> List)

This method computes the eigenvalues and the eigenvectors, if selected during the initialization. It requires two mandatory **Math::Libgsl::Matrix** objects (refer to the amazing C Library documentation for the meaning of those two matrices and the details of the computation). The optional named argument **:$schur-S** requires that it computes the full Schur form S. The optional named argument **:$schur-T** requires that it computes the full Schur form T. The optional named argument **:$balance** requires that a balancing transformation is applied to the matrix prior to computing eigenvalues (currently ignored by the underlying C library; TBI). The optional named argument **:$schur-vectors** requires that it also computes the Schur vectors. The optional named argument **:$sort** specifies the required sort order.

This method outputs a List of values: one **Math::Libgsl::Vector::Complex64** and one **Math::Libgsl::Vector** object, which contain the eigenvalues (see the C library documentation for the meaning of these two vectors), an optional **Math::Libgsl::Matrix::Complex64**, which contains the eigenvectors if they were requested. If the Schur vectors were requested the left and right Schur vectors are returned as **Math::Libgsl::Matrix** objects. On exit, if **$schur-S** is True, the first matrix **$A** will contain the Schur form S; if **$schur-T** is True, the second matrix **$B** will contain the Schur form T.

# C Library Documentation

For more details on libgsl see <https://www.gnu.org/software/gsl/>. The excellent C Library manual is available here <https://www.gnu.org/software/gsl/doc/html/index.html>, or here <https://www.gnu.org/software/gsl/doc/latex/gsl-ref.pdf> in PDF format.

# Prerequisites

This module requires the libgsl library to be installed. Please follow the instructions below based on your platform:

## Debian Linux and Ubuntu 20.04+

```
sudo apt install libgsl23 libgsl-dev libgslcblas0

```

That command will install libgslcblas0 as well, since it's used by the GSL.

## Ubuntu 18.04

libgsl23 and libgslcblas0 have a missing symbol on Ubuntu 18.04. I solved the issue installing the Debian Buster version of those three libraries:

* <http://http.us.debian.org/debian/pool/main/g/gsl/libgslcblas0_2.5+dfsg-6_amd64.deb>
* <http://http.us.debian.org/debian/pool/main/g/gsl/libgsl23_2.5+dfsg-6_amd64.deb>
* <http://http.us.debian.org/debian/pool/main/g/gsl/libgsl-dev_2.5+dfsg-6_amd64.deb>

# Installation

To install it using zef (a module management tool):

```
$ zef install Math::Libgsl::Eigensystem

```

# AUTHOR

Fernando Santagata [nando.santagata@gmail.com](mailto:nando.santagata@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2021 Fernando Santagata

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


## dist_cpan-ROBERTLE-ReadWriteLock.md
# ReadWriteLock

... A lock with shared/exclusive access modes, for the Raku language.

## Features

* Does what a basic `Lock` does, just slower and with more bugs ;)
* Reentrant: the lock can be taken again by a thread that is already holding it
  It needs to be unlocked the same number of times it was locked before it can
  be taken by another thread
* Fair in the sense of first-come-first-serve
* Shared access: multiple 'readers' can share the lock, yet access is mutually
  exclusive between 'readers' and 'writers'
* Lock Upgrade: you can upgrade a shared access mode to an exclusive without
  unlocking first, if no other thread is interferring. In this case you do not
  need to unlock twice.

## Planned Features

* Read-for-write access mode that guarantees that a lock upgrade can be taken
* Async version that returns threads to the threadpool and returns a promise
  from lock()

## Example Usage

```
use ReadWriteLock;

my $l = ReadWriteLock.new;

my $thread-a = Thread.start({
    $l.lock-shared();
    for ^5 {
        sleep 1;
        say "thread A doing something under protection of the lock";
    }
    $l.unlock();
});

my $thread-b = Thread.start({
    $l.protect-shared({
        for ^5 {
            sleep 1;
            say "thread B doing something under protection of the lock";
        }
    });
});

my $thread-c = Thread.start({
    $l.protect-exclusive({
        for ^5 {
            sleep 1;
            say "thread C doing something under exclusive protection of the lock";
        }
    });
});

$thread-a.join;
$thread-b.join;
$thread-c.join;

```

## Documentation

Please see the POD in lib/ReadWriteLock.rakumod for more documentation and usage
scenarios.

## License

ReadWriteLock is licensed under the [Artistic License 2.0](https://opensource.org/licenses/Artistic-2.0).

## Feedback and Contact

Please let me know what you think: Robert Lemmen [robertle@semistable.com](mailto:robertle@semistable.com)


## dist_cpan-RYNIX-Graphics-TinyTIFF.md
# NAME

Graphics::TinyTIFF - Perl6 bindings to [a slightly modified] TinyTIFF

# DEPENDANCIES

## Unix

```
git clone https://github.com/ryn1x/TinyTIFF.git
cd TinyTIFF
mkdir build
cd build
cmake ..
make
sudo make install

```

## Windows

```
git clone https://github.com/ryn1x/TinyTIFF.git
cd TinyTIFF
mkdir build
cd build
cmake ..
cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE -G "Visual Studio 15 2017 win64" ..
build generated ".sln" file with visual studio

```

# INSTALL

zef install Graphics::TinyTIFF

# SYNOPSIS

```
#!/usr/bin/env perl6

use v6.c;
use NativeCall;
use Graphics::TinyTIFF;

########## reader ##########

my $tiff = TinyTIFFReader_open('cell.tif');
my $frames = TinyTIFFReader_countFrames($tiff);
my $bits = TinyTIFFReader_getBitsPerSample($tiff, 0);
my $width = TinyTIFFReader_getWidth($tiff);
my $height = TinyTIFFReader_getHeight($tiff);
my $description = TinyTIFFReader_getImageDescription($tiff);

my $size = $width * $height;
my $sample-data := CArray[uint8].allocate($size);

TinyTIFFReader_getSampleData($tiff, $sample-data, 0);

# you now have $sample-data for the current frame
# and can manipulate it as you wish!

my $format = TinyTIFFReader_getSampleFormat($tiff);
my $samples-per-pixel = TinyTIFFReader_getSamplesPerPixel($tiff);
my $has-next = ?TinyTIFFReader_hasNext($tiff);
TinyTIFFReader_readNext($tiff) if $has-next;
my $success = ?TinyTIFFReader_success($tiff);
my $was-error = ?TinyTIFFReader_wasError($tiff);
my $last-error = TinyTIFFReader_getLastError($tiff) if $was-error;
TinyTIFFReader_close($tiff);

########## writer ##########

my $tiff-file = TinyTIFFWriter_open('cell2.tif', $bits, $width, $height);
my $description-size = TinyTIFFWriter_getMaxDescriptionTextSize();
TinyTIFFWriter_writeImageVoid( $tiff-file, $sample-data);
TinyTIFFWriter_close( $tiff-file, 'test');

print qq:to/END/;
    frames            -> $frames
    bits              -> $bits
    width             -> $width
    height            -> $height
    description       -> $description
    format            -> $format
    samples per pixel -> $samples-per-pixel
    has next?         -> $has-next
    success?          -> $success
    was error?        -> $was-error
    description size  -> $description-size
    sample data       -> $sample-data[^3] ...
    END

```

Output:

```
frames            -> 1
bits              -> 8
width             -> 191
height            -> 159
description       -> image description
format            -> 1
samples per pixel -> 1
has next?         -> False
success?          -> True
was error?        -> False
description size  -> 1024
sample data       -> 118 116 112 ...

```

# SUBROUTINES

### sub TinyTIFFReader\_open

```
sub TinyTIFFReader_open(
    str $filename
) returns NativeCall::Types::Pointer

```

open tiff file for reading, returns tiff pointer

### sub TinyTIFFReader\_getSampleData

```
sub TinyTIFFReader_getSampleData(
    NativeCall::Types::Pointer $tiff,
    NativeCall::Types::CArray $sample-data is rw,
    uint16 $sample
) returns int32

```

read data from current frame into supplied buffer

### sub TinyTIFFReader\_close

```
sub TinyTIFFReader_close(
    NativeCall::Types::Pointer $tiff
) returns Mu

```

close the tiff file

### sub TinyTIFFReader\_getBitsPerSample

```
sub TinyTIFFReader_getBitsPerSample(
    NativeCall::Types::Pointer $tiff,
    int32 $sample
) returns uint16

```

return bits per sample of current frame

### sub TinyTIFFReader\_getWidth

```
sub TinyTIFFReader_getWidth(
    NativeCall::Types::Pointer $tiff
) returns uint32

```

return width of current frame

### sub TinyTIFFReader\_getHeight

```
sub TinyTIFFReader_getHeight(
    NativeCall::Types::Pointer $tiff
) returns uint32

```

return height of current frame

### sub TinyTIFFReader\_countFrames

```
sub TinyTIFFReader_countFrames(
    NativeCall::Types::Pointer $tiff
) returns uint32

```

return number of frames

### sub TinyTIFFReader\_getSampleFormat

```
sub TinyTIFFReader_getSampleFormat(
    NativeCall::Types::Pointer $tiff
) returns uint16

```

return sample format of current frame

### sub TinyTIFFReader\_getSamplesPerPixel

```
sub TinyTIFFReader_getSamplesPerPixel(
    NativeCall::Types::Pointer $tiff
) returns uint16

```

return samples per pixel of current frame

### sub TinyTIFFReader\_getImageDescription

```
sub TinyTIFFReader_getImageDescription(
    NativeCall::Types::Pointer $tiff
) returns str

```

return image descrition of current frame

### sub TinyTIFFReader\_hasNext

```
sub TinyTIFFReader_hasNext(
    NativeCall::Types::Pointer $tiff
) returns int32

```

retun non-zero if another frame exists

### sub TinyTIFFReader\_readNext

```
sub TinyTIFFReader_readNext(
    NativeCall::Types::Pointer $tiff
) returns int32

```

read the next frame from a multi-frame tiff

### sub TinyTIFFReader\_success

```
sub TinyTIFFReader_success(
    NativeCall::Types::Pointer $tiff
) returns int32

```

return non-zero if no error in last function call

### sub TinyTIFFReader\_wasError

```
sub TinyTIFFReader_wasError(
    NativeCall::Types::Pointer $tiff
) returns int32

```

return non-zero if error in last function call

### sub TinyTIFFReader\_getLastError

```
sub TinyTIFFReader_getLastError(
    NativeCall::Types::Pointer $tiff
) returns str

```

return last error message

### sub TinyTIFFWriter\_open

```
sub TinyTIFFWriter_open(
    str $filename,
    uint16 $bits-per-sample,
    uint32 $width,
    uint32 $height
) returns NativeCall::Types::Pointer

```

create a new tiff file, returns tiff-file pointer

### sub TinyTIFFWriter\_getMaxDescriptionTextSize

```
sub TinyTIFFWriter_getMaxDescriptionTextSize() returns int32

```

get max size for image descrition

### sub TinyTIFFWriter\_writeImageDouble

```
sub TinyTIFFWriter_writeImageDouble(
    NativeCall::Types::Pointer $tiff-file,
    NativeCall::Types::CArray $sample-data is rw
) returns Mu

```

writes row-major image data to a tiff file

### sub TinyTIFFWriter\_writeImageFloat

```
sub TinyTIFFWriter_writeImageFloat(
    NativeCall::Types::Pointer $tiff-file,
    NativeCall::Types::CArray $sample-data is rw
) returns Mu

```

writes row-major image data to a tiff file

### sub TinyTIFFWriter\_writeImageVoid

```
sub TinyTIFFWriter_writeImageVoid(
    NativeCall::Types::Pointer $tiff-file,
    NativeCall::Types::CArray $sample-data is rw
) returns Mu

```

writes row-major image data to a tiff file

### sub TinyTIFFWriter\_close

```
sub TinyTIFFWriter_close(
    NativeCall::Types::Pointer $tiff-file,
    str $image-description
) returns Mu

```

close the tiff and write image description to first frame

# COPYRIGHT AND LICENSE

Copyright 2018 ryn1x

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