# LOGO

                          ⢀⣀⡤ ⢀⣤⣿⡗ ⣀⣀⣀
              ⢀⣤⣤⣤⣄⡀    ⣠⡶⠿⠛⣹⡾⠛⢁⡼⠟⢛⠉⠉⠉⣉⣣⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⡄
          ⢉⠻⣯⣉⡛⠒⠻⡷⢮⡙⠳⣤⡐⣾⠟⣀⣴⠋⠁⣀⡴⠋ ⣠⡟ ⠐⠚⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⢩⠛
          ⠘⣧ ⠹⣿⡳⡀⠙⢦⡈⠳⠈⢱⡟ ⠋⣼⣿⣿⢿⠁⠰⣶⠏⢐⡆⢠  ⣠⣖⣢⠤⠶⠶⠂ ⡽⢃  ⣀
           ⠈⢗⣲⠞⠓⠛⢦⡌⡿  ⡾⠃  ⣿⣿⡾   ⣿ ⣼⣠⠏⢀⡾⣿⠟⣂⣠⡤⠤⠴⠶⠛⠛⠛⢋⡿
       ⢀⡴⡲⠹⠍⠁ ⠐⢶⡂⠈⣓⠱⣆⡼⠃  ⢰⣿⡟⢳ ⢀⣾⢇⡜⠋⠁⣰⣯⠾⠷⠚⠉ ⢀⣴⠎    ⢸⡇
       ⠘⠙⠳⠤⣕ ⠳⣄ ⠉⠓⢴⣱⣿⡅⣀⣤⠾⣟⣯⣤⣶⡶⢿⣿⣯⠆ ⢈⣽⠃⣀⣀⣠⣴⣾⣯⠄     ⣴⠇
          ⢀⣹⣶⡀⢈⣷⣶⣤⣼⣿⡿⢗⡋⣩⣶⡟⣛⣿⣿⣷⣾⣛⣉⣀⡤⠾⠛⠒⠋⠉⠛⣿⡿⠋     ⢠⡏
         ⠙⠛⣲⡶⣤⣤⣿⡿⠋⠁⠻⠿⠛⠛⠙⠛⠛⠋⠉⠹⠿⠿⢿⣿⣏⣠⡖⣀⢀⣠⠤⢀⣈⣳⣄     ⢨⣶⣦⡤⣄⣀
          ⠉⢁⣴⣋⣸⠟       ⣰⣶⠴⠒      ⠈⠛⠻⢿⣿⣿⡛⠋⠉⠙⣿   ⣠⡶⣫⣭⠶⣭⡀
         ⢀⣴⠟⠉⢡⡏⡼   ⢠⡞  ⠉            ⢸⣿⡿⢿⡒⠒⠲⠿⠶⠶⠶⠟⠋⠁⣀⣀⣀⠉⠳⣄
        ⠲⣿⠷⠃⢀⣾⠷⠿⠦⢤⣤⡟   ⢀⣀⣤⣶⣯⣥⣤⣤⡞⠁   ⠈⣼⣿⣷⣝⡳⠤⣤⣀⣀   ⠉  ⠙⠻⢦⣈⢳⡄
       ⢀⡼⢋⣤⠴⠋⠁   ⣴⠿⠿⢶⣶⣿⣿⠟⠛⢻⣿⣿⠟⠁      ⠈⠻⣿⡍⠛⠷⣦⣄⡀⠳⢤⡀      ⠙⠧⣄
      ⣠⣿⠟⠉    ⣀⣀⡀ ⣤⣤⣼⣿⣿⣷⣂⣴⣿⡿⠋      ⠰⡆ ⢻⣿⣿⣶⣄⡈⠻⣝ ⠈⠙⠲⣤⣀⡀  ⠑⢦⣌⡙⠒
     ⢰⡟⠁     ⠛⢩⠶⠖⠛⣀⡏⠉⠙⠿⣿⣿⡟⠉         ⣷  ⣿⣿⣧⡙⢷⣄⡈⠂     ⠉⠉⠙⢷⡄⠈⠛⢦
    ⣠⡿⠛⢶⣦⣤⣤⣴⣶ ⠈⡿⠟⠛⠉⠁⢀⣀⣀ ⠉⠙⠛⠒⠂       ⡿ ⣽⣿⠘⢻⣷⡀⠈⠉⠉         ⠹⣆  ⠁
    ⡏  ⢸⣿⡿⠉⠙⠋ ⠈      ⠈⠉⣉⠅ ⠓⠲⢤⣄⡀    ⣼⠃ ⢿⣿  ⣿⠇⢠⡀       ⠠⣄⣄ ⢹⡆
    ⣷⡀  ⡿       ⣀⠔   ⣠⣞⣁⣀⣠⣤⣤⣷⣌⠙⢦⡀⢀⡾⠃  ⢸⣿⡆⣻⠇  ⢹⣄       ⢹⡌⢳⣜⡟
    ⢻⣧⣠⣸⡇          ⣠⡾⠟⠛⠉⣥⡾⢿⣿⣿⣿⣆ ⠙⠃    ⣿⢏⣿⡿⡀   ⠻⣷⢤⡀    ⢸⡇ ⢿⡇
     ⠉⢻⢿⣿⣶⣤⣤⣀⣀⣀⣀⣤⣴⡿⠋⠁⣠⡴⠟⢁⣴⣿⣿⣿⣿⣿⡆     ⣼⡟⣼⣿⣷⢻⡜⣆  ⠘⢷⡙  ⣠⣤⡿ ⠈⠛⠁
      ⠘⠦⢿⣍⠉⠉⠉⠙⢿⠩⢻⣿⣾⠞⠛⠁  ⣾⠏⠈⢻⣿⣿⣿⣿⡀⡀   ⢻⣰⠟⠁⠘⢦⡻⣿⡆  ⢸⣷  ⣿⡟⠁
         ⠙⠋⠛⠳⣶⣶⠷⢾⣿⣿    ⢀⣿   ⢻⣿⣿⣿⡧   ⢀⣴⠋    ⠁⠈⢳  ⣸⠙⣦⢰⡟
             ⠘⣿⣄⢼⣿⣿⣇⠒⢢⣿⣼⣧⡀ ⢤⡀⣿⣿⣿⡧  ⢀⣾⠃  ⢀⢠⡆  ⡞⢀⡴⣃⣸⡟⠳⣇
              ⠹⡽⣾⣿⠹⣿⣆⣾⢯⣿⣿ ⡞ ⠻⣿⣿⣿⠁ ⢠⣿⢏  ⡀ ⡟  ⢀⣴⣿⠃⢁⡼⠁ ⠈
                ⠈⠛ ⢻⣿⣧⢸⢟⠶⢾⡇  ⣸⡿⠁ ⢠⣾⡟⢼  ⣷ ⡇ ⣰⠋⠙⠁
                   ⠈⣿⣻⣾⣦⣇⢸⣇⣀⣶⡿⠁⣀⣀⣾⢿⡇⢸  ⣟⡦⣧⣶⠏ unleashed
                    ⠸⢿⡍⠛⠻⠿⠿⠿⠋⣠⡾⢋⣾⣏⣸⣷⡸⣇⢰⠟⠛⠻⡄  v1.29
                      ⢻⡄   ⠐⠚⠋⣠⡾⣧⣿⠁⠙⢳⣽⡟
                      ⠈⠳⢦⣤⣤⣀⣤⡶⠛ ⠈⢿⡆  ⢿⡇
                            ⠈    ⠈⠓  ⠈

# NAME

e - beast mode unleashed

# SYNOPSIS

Add a trace marker:

    $ perl -Me -e 'sub f1 { trace } sub f2 { f1 } f2'

Watch a reference for changes:

    $ perl -Me -e 'my $v = {}; sub f1 { watch( $v ) } sub f2 { f1; $v->{a} = 1 } f2'

    $ perl -Me -e '
        package A {
            use e;
            my %h = ( aaa => 111 );

            watch(\%h);

            sub f1 {
                $h{b} = 1;
            }

            sub f2 {
                f1();
                delete $h{aaa};
            }
        }

        A::f2();
    '

Benchmark two snippets of code:

    $ perl -Me -e 'n { slow => sub{ ... }, fast => sub{ ... }}, 10000'

Launch the Runtime::Debugger:

    $ perl -Me -e 'repl'

Invoke the Tiny::Prof:

    $ perl -Me -e 'prof'

Convert a data structure to json:

    $ perl -Me -e 'say j { a => [ 1..3] }'

Convert a data structure to yaml:

    $ perl -Me -e 'say yml { a => [ 1..3] }'

Pretty print a data structure:

    $ perl -Me -e 'p { a => [ 1..3] }'

Data dump a data structure:

    $ perl -Me -e 'd { a => [ 1..3] }'

Devel::Peek dump a data structure:

    $ perl -Me -e 'dd { a => [ 1..3] }'

Print data as a table:

    $ perl -Me -e 'table( [qw(key value)], [qw(red 111)], [qw(blue 222)] )'
    +------+-------+
    | key  | value |
    +------+-------+
    | red  | 111   |
    | blue | 222   |
    +------+-------+

Encode/decode UTF-8:

    $ perl -Me -e 'printf "%#X\n", ord for split //, enc "\x{5D0}"'
    0XD7
    0X90

    $ perl -C -Me -e 'say dec "\xD7\x90"'
    $ perl -Me -e 'utf8; say dec "\xD7\x90"'
    א

# DESCRIPTION

This module imports many features that make
one-liners and script debugging much faster.

It has been optimized for performance to not
import all features right away:
thereby making its startup cost quite low.

# SUBROUTINES

## Investigation

### repl

Add a breakpoint to code.

Basically inserts a Read Evaluate Print Loop.

Enable to analyze code in the process.

    CODE ...

    # Breakpoint
    repl

    CODE ...

Simple debugger on the command line:

    $ perl -Me -e 'repl'

### trace

Show a stack trace.

    trace( OPTIONS )

OPTIONS:

    -levels  => NUM,           # How many scope levels to show.
    NUM,                       # Same.

    -raw => 1,                 # Include internal calls.
    -NUM,                      # Same.

    -message => STR,           # Message to display.
    STR,                       # Same.

### watch

Watch a reference for changes.

    watch( $ref, OPTIONS )

OPTIONS:

    -clone => 0,               # Will not watch cloned objects.

    -methods => "fetch",       # Monitor just this method.
    -methods => [ "fetch" ],   # Same.

    -levels  => NUM,           # How many scope levels to show.
    NUM,                       # Same.

    -raw => 1,                 # Include internal calls.
    -NUM,                      # Same.

    -message => STR,           # Message to display.
    STR,                       # Same.

### prof

Profile the code from this point on.

    my $obj = prof;
    ...
    # $obj goes out of scope and builds results.

### n

Benchmark and compare different pieces of code.

    Time single block of code.
    n sub{ ... };
    n sub{ ... }, 100000;

    # Compare blocks of code.
    n {
        slow => sub{ ... },
        fast => sub{ ... },
    };
    n {
        slow => sub{ ... },
        fast => sub{ ... },
    }, 10000;

    $ perl -Me -e '$v = 333; n { concat => sub { 111 . $v }, interp => sub { "111$v" }, list => sub { 111,$v } }, 100000000'

              Rate interp concat   list
    interp  55248619/s     --    -6%   -62%
    concat  58479532/s     6%     --   -60%
    list   144927536/s   162%   148%     --

## Format Conversions

### j

JSON Parser.

    my $bytes = j([1, 2, 3]);
    my $bytes = j({foo => 'bar'});
    my $value = j($bytes);

Encode Perl data structure or decode JSON with ["j" in Mojo::JSON](https://metacpan.org/pod/Mojo%3A%3AJSON#j).

Convert Perl object to JSON string:

    $ perl -Me -e 'say j { a => [1..3]}'

Convert JSON string to Perl object:

    $ perl -Me -e 'p j q({"a":[1,2,3]})'

### x

XML parser.

    my $dom = x('<div>Hello!</div>');

Turn HTML/XML input into [Mojo::DOM](https://metacpan.org/pod/Mojo%3A%3ADOM) object.

    $ perl -Me -e 'say x("<div>hey</dev>")->at("div")->text'

Force HTML semantics:

    $ perl -Me -e 'say x->xml(0)->parse("<Tag>Name</Tag>")'
    <tag>Name</tag>

Force XML semantics (case sensitive tags and more):

    $ perl -Me -e 'say x->xml(1)->parse("<Tag>Name</Tag>")'
    <Tag>Name</Tag>

### yml

YAML parser.

Convert Perl object to YAML string:

    $ perl -Me -e 'say yml { a => [1..3]}'

Convert YAML string to Perl object:

    $ perl -Me -e 'p yml "---\na:\n- 1\n- 2\n- 3"'

### clone

Storable's deep clone.

    $ perl -Me -e '
        my $arr1   = [ 1..3 ];
        my $arr2   = clone $arr1;
        $arr2->[0] = 111;

        say $arr1;
        p $arr1;

        say "";
        say $arr2;
        p $arr2;
    '

    # Output:
    ARRAY(0x5d0b8a408518)
    [
        [0] 1,
        [1] 2,
        [2] 3,
    ]

    ARRAY(0x5d0b8a42d9e0)
    [
        [0] 111,
        [1] 2,
        [2] 3,
    ]

### enc

Encode UTF-8 code point to a byte stream:

    $ perl -Me -e 'printf "%#X\n", ord for split //, enc "\x{5D0}"'
    0XD7
    0X90

### dec

Decode a byte steam to UTF-8 code point:

    $ perl -C -Me -e 'say dec "\xD7\x90"'
    א

### utf8

Set STDOUT and STDERR as UTF-8 encoded.

If given a filehandle, will set the encoding
for it to UTF-8.

    utf8($fh);

## Enhanced Types

### b

Work with strings.

    my $stream = b('lalala');

Turn string into a [Mojo::ByteStream](https://metacpan.org/pod/Mojo%3A%3AByteStream) object.

    $ perl -Me -e 'b(g("mojolicious.org")->body)->html_unescape->say'

### c

Work with arrays.

    my $collection = c(1, 2, 3);

Turn list into a [Mojo::Collection](https://metacpan.org/pod/Mojo%3A%3ACollection) object.

### set

Work with sets.

    my $set = set(2,4,6,4);

Turn list into a [Set::Scalar](https://metacpan.org/pod/Set%3A%3AScalar) object.

    $ perl -Me -e 'say set(2,4,6,2)'
    (2 4 6)

Get elements:

    $ perl -Me -e 'say for sort(set(2,4,6,2)->elements)'
    $ perl -Me -e 'say for sort(set(2,4,6,2)->@*)'
    2
    4
    6

Check for existence of an element:

    $ perl -Me -e 'say set(2,4,6,2)->has(7)'
    $ perl -Me -e 'say set(2,4,6,2)->has(4)'
    1

Intersection:

    $ perl -Me -e 'say set(2,4,6,2) * set(3,4,5,6)'
    (4 6)

Create a new universe:

    # Universe 1:
    # ...
    Set::Scalar::Universe->new->enter;
    # Universe 2:
    # ...

Operations:

    set                         value

    $a                          (a b c d e _ _ _ _)
    $b                          (_ _ c d e f g _ _)
    $c                          (_ _ _ _ e f g h i)

    union:        $a + $b       (a b c d e f g _ _)
    union:        $a + $b + $c  (a b c d e f g h i)
    intersection: $a * $b       (_ _ c d e _ _ _ _)
    intersection: $a * $b * $c  (_ _ _ _ e _ _ _ _)
    difference:   $a - $b       (a b _ _ _ _ _ _ _)
    difference:   $a - $b - $c  (a b _ _ _ _ _ _ _)
    unique:       $a % $b       (a b _ _ _ f g _ _)
    symm_diff:    $a / $b       (a b _ _ _ f g _ _)
    complement:   -$a           (_ _ c d e f g h i)

## Files Convenience

### f

Work with files.

    my $path = f('/home/sri/foo.txt');

Turn string into a [Mojo::File](https://metacpan.org/pod/Mojo%3A%3AFile) object.

    $ perl -Me -e 'say r j f("hello.json")->slurp'

## Math Help

### max

Get the biggest number in a list.

    $ perl -Me -e 'say max 2,4,1,3'
    4

### min

Get the smallest number in a list.

    $ perl -Me -e 'say max 2,4,1,3'
    1

## Output

### say

Obnoxious print with a newline.

    $ perl -Me -e 'say 123'
    $ perl -Me -e 'say for 1..3'

Always sends output to the terminal even
when STDOUT and/or STDERR are redirected:

    $ perl -Me -e '
        say "Shown before";
        close *STDOUT;
        close *STDERR;
        say "Shown with no stdout/err";
        print "Print not seen\n";
    '
    111
    222

### p

Pretty data printer.

    $ perl -Me -e 'p [1..3]'

### np

Return pretty printer data.

    $ perl -Me -e 'my $v = np [1..3]; say "got: $v"'

Can be used with `say` to output to the terminal
(incase STDOUT/STDERR are redirected):

    $ perl -Me -e '
        close *STDOUT;
        close *STDERR;
        say np [ 1.. 3 ];
    '

### d

Data dumper.

    $ perl -Me -e 'd [1..3]'

### dd

Internal data dumper.

    $ perl -Me -e 'dd [1..3]'

### dye

Color a string.

    $ perl -Me -e 'say dye 123, "RED"'

### table

Print data as a table:

    $ perl -Me -e 'table( [qw(key value)], [qw(red 111)], [qw(blue 222)] )'
    +------+-------+
    | key  | value |
    +------+-------+
    | red  | 111   |
    | blue | 222   |
    +------+-------+

Context sensitive!

    - Void   - output table.
    - List   - return individual lines.
    - Scalar - return entire table as a string.

## Web Related

### g

    my $res = g('example.com');
    my $res = g('http://example.com' => {Accept => '*/*'} => 'Hi!');
    my $res = g('http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
    my $res = g('http://example.com' => {Accept => '*/*'} => json => {a => 'b'});

Perform `GET` request with ["get" in Mojo::UserAgent](https://metacpan.org/pod/Mojo%3A%3AUserAgent#get) and return resulting [Mojo::Message::Response](https://metacpan.org/pod/Mojo%3A%3AMessage%3A%3AResponse) object.

    $ perl -Me -e 'say g("mojolicious.org")->dom("h1")->map("text")->join("\n")'

### post

    my $res = post('example.com');
    my $res = post('http://example.com' => {Accept => '*/*'} => 'Hi!');
    my $res = post('http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
    my $res = post('http://example.com' => {Accept => '*/*'} => json => {a => 'b'});

Perform `POST` request with ["get" in Mojo::UserAgent](https://metacpan.org/pod/Mojo%3A%3AUserAgent#get) and return resulting [Mojo::Message::Response](https://metacpan.org/pod/Mojo%3A%3AMessage%3A%3AResponse) object.

    $ perl -Me -e 'say post("mojolicious.org")->dom("h1")->map("text")->join("\n")'

### l

Work with URLs.

    my $url = l('https://mojolicious.org');

Turn a string into a [Mojo::URL](https://metacpan.org/pod/Mojo%3A%3AURL) object.

    $ perl -Me -e 'say l("/perldoc")->to_abs(l("https://mojolicious.org"))'

## Asynchronous

This sector includes commands to run asynchronous
(or pseudo-async) operations.

It is not entirely clear which method to always use.

`runf` limits to number of action or 20 (whichever is smaller).

`runt` and `runio` have no such limits.

Typically using threads (with `runt`) seems to be fastest.

Some statistics using different run commands:

    $ gitb status -d
           s/iter   runt  runio   runf series
    runt     1.74     --   -35%   -59%   -74%
    runio    1.12    55%     --   -36%   -59%
    runf    0.716   142%    56%     --   -36%
    series  0.456   281%   146%    57%     --

    $ gitb branch -d
              Rate   runt   runf series  runio
    runt   0.592/s     --   -71%   -81%   -83%
    runf    2.02/s   240%     --   -34%   -42%
    series  3.05/s   415%    51%     --   -12%
    runio   3.47/s   486%    72%    14%     --

    $ gitb pull -d
           s/iter  runio series   runt   runf
    runio    4.27     --    -7%   -21%   -33%
    series   3.97     8%     --   -15%   -28%
    runt     3.38    26%    17%     --   -15%
    runf     2.87    49%    38%    18%     --

### runf

Run tasks in parallel using [Parallel::ForkManager](https://metacpan.org/pod/Parallel%3A%3AForkManager).

Returns the results.

    $ perl -Me -e '
        p {
            runf
            map {
                my $n = $_;
                sub{ $n => $n**2 };
            } 1..5
        }
    '
    {
        1 => 1,
        2 => 4,
        3 => 9,
        4 => 16,
        5 => 25,
    }

Takes much overhead to start up!

Will use up to 20 processes.

### runio

Run tasks in parallel using [Mojo::IOLoop](https://metacpan.org/pod/Mojo%3A%3AIOLoop).

Returns the results.

    $ perl -Me -e '
        p {
            runio
            map {
                my $n = $_;
                sub{ $n => $n**2 };
            } 1..5
        }
    '
    {
        1 => 1,
        2 => 4,
        3 => 9,
        4 => 16,
        5 => 25,
    }

This is apparently better to use for IO related tasks.

### runt

Run tasks in parallel using [threads](https://metacpan.org/pod/threads).

Returns the results.

    $ perl -Me -e '
        p {
            runt
            map {
                my $n = $_;
                sub{ $n => $n**2 };
            } 1..5
        }
    '
    {
        1 => 1,
        2 => 4,
        3 => 9,
        4 => 16,
        5 => 25,
    }

This is the fastest run\* command usually.

## Package Tools

### monkey\_patch

Insert subroutines into the symbol table.

Extracted from Mojo::Util for performance.

Import methods into another package
(as done in this module):

    $ perl -e '
        package A;
        use e;
        sub import {
            my $c = caller();
            monkey_patch
                $c,
                new => sub { say "Im new" };
        }
        package main;
        A->import;
        new();
    '
    Im new

Import methods into the same package
(probably not so useful):

    $ perl -e '
        package A;
        use e;
        sub import {
            my $c = caller();
            monkey_patch
                $c,
                new => sub { say "Im new" };
        }
        A->import;
        A->new();
    '
    Im new

Perhaps can be updated based on the outcome
of this issue:
[https://github.com/mojolicious/mojo/pull/2173](https://github.com/mojolicious/mojo/pull/2173)

### pod

Work with perl pod.

### import

\[Internal\] Imports the DSL into another package.

Can be used in a sub class to import this class
plus its own commands like this:

    package e2;
    use parent qw( e );

    sub import {
        my ( $class ) = @_;
        my $class = caller;
        $class->SUPER::import( $caller );
        $class->can("monkey_patch")->(
            $caller,
            my_command_1 => sub {},
            my_command_2 => sub {},
            my_command_3 => sub {},
        );
    }

# AUTHOR

Tim Potapov, `<tim.potapov[AT]gmail.com>`

# BUGS

Please report any bugs or feature requests to
[https://github.com/poti1/e/issues](https://github.com/poti1/e/issues).

# SUPPORT

You can find documentation for this module
with the perldoc command.

    perldoc e

You can also look for information at:

[https://metacpan.org/pod/e](https://metacpan.org/pod/e)

[https://github.com/poti1/e](https://github.com/poti1/e)

Logo was generated using: [https://emojicombos.com/dot-art-editor](https://emojicombos.com/dot-art-editor)

# LICENSE AND COPYRIGHT

This software is Copyright (c) 2024 by Tim Potapov.

This is free software, licensed under:

    The Artistic License 2.0 (GPL Compatible)
