App-riap

 view release on metacpan or  search on metacpan

lib/App/riap.pm  view on Meta::CPAN

    my $res = $self->riap_parse_url($surl);
    die "Can't parse url $surl\n" unless $res;
    $pwd = $res->{path};
    $self->state(pwd        => $pwd);
    $self->state(start_pwd  => $pwd);
    $self->run_cd($pwd);

    $self;
}

# override, readline workarounds
sub cmdloop {
    require Carp;
    require IO::Stty;
    require Signal::Safety;

    my $o = shift;
    my $rl = $o->{term};

    local $SIG{INT} = sub {
        # save history when we are interrupted
        $o->save_history;
        print STDERR "Interrupted\n";
        if ($rl->ReadLine eq 'Term::ReadLine::Gnu') {
            IO::Stty::stty(\*STDIN, 'echo');
        }
        exit 1;
    };

    local $SIG{__DIE__} = sub {
        IO::Stty::stty(\*STDIN, 'echo');
        $o->setting('debug_stack_trace') ? Carp::confess(@_) : die(@_);
    };

    local $SIG{__WARN__} = sub {
        IO::Stty::stty(\*STDIN, 'echo');
        $o->setting('debug_stack_trace') ? Carp::cluck(@_) : warn(@_);
    };

    # some workaround for Term::ReadLine
    # say "D0, rl=", $rl->ReadLine;
    my $attribs = $rl->Attribs;
    if ($rl->ReadLine eq 'Term::ReadLine::Gnu') {
        # TR::Gnu traps our INT handler
        # ref: http://www.perlmonks.org/?node_id=1003497
        $attribs->{catch_signals} = 0;
    } elsif ($rl->ReadLine eq 'Term::ReadLine::Perl') {
        # TR::Perl messes up colors
        # doesn't do anything?
        #$rl->ornaments(0);
        #$attribs->{term_set} = ["", "", "", ""];
    }

    $o->{stop} = 0;
    $o->preloop;
    while (1) {
        my $line;
        {
            no warnings 'once';
            local $Signal::Safety = 0; # limit the use of unsafe signals
            $line = $o->readline($o->prompt_str);
        }
        last unless defined($line);
        my $time1 = time();
        $o->cmd($line);
        my $time2 = time();
        if ($o->setting('debug_time_command')) {
            say sprintf("  %.3fs", ($time2-$time1));
        }
        last if $o->{stop};
    }
    $o->postloop;
}

sub mainloop { goto \&cmdloop }

sub colorize {
    my ($self, $text, $color) = @_;
    if ($self->{use_color}) {
        ansifg($color) . $text . "\e[0m";
    } else {
        $text;
    }
}

sub _json_obj {
    state $json;
    if (!$json) {
        require JSON::MaybeXS;
        $json = JSON::MaybeXS->new->allow_nonref;
    }
    $json;
}

sub json_decode {
    my ($self, $arg) = @_;
    $self->_json_obj->decode($arg);
}

sub json_encode {
    my ($self, $arg) = @_;
    my $data = $cleanser->clone_and_clean($arg);
    #use Data::Dump; dd $data;
    $self->_json_obj->encode($data);
}

sub settings_filename {
    my $self = shift;
    $ENV{RIAPRC} // "$ENV{HOME}/.riaprc";
}

sub history_filename {
    my $self = shift;
    $ENV{RIAP_HISTFILE} // "$ENV{HOME}/.riap_history";
}

sub known_settings {
    state $settings;
    if (!$settings) {
        require Perinci::Result::Format;
        $settings = {

lib/App/riap.pm  view on Meta::CPAN

        my $res = Config::IOD::Reader->new->read_file($filename);
        last unless $res->{GLOBAL};
        for (sort keys %{$res->{GLOBAL}}) {
            $self->setting($_, $res->{GLOBAL}{$_});
        }
    }
}

sub save_settings {
    die "Unimplemented";
}

sub clear_history {
    my $self = shift;

    if ($self->{term}->Features->{setHistory}) {
        $self->{term}->SetHistory();
    }
}

sub load_history {
    my $self = shift;

    if ($self->{term}->Features->{setHistory}) {
        my $filename = $self->history_filename;
        return unless $filename;
        if (-r $filename) {
            log_trace("Loading history from %s ...", $filename);
            open(my $fh, '<', $filename)
                or die "Can't open history file $filename: $!\n";
            chomp(my @history = <$fh>);
            $self->{term}->SetHistory(@history);
            close $fh or die "Can't close history file $filename: $!\n";
        }
    }
}

sub save_history {
    my $self = shift;

    if ($self->{term}->Features->{getHistory}) {
        my $filename = $self->history_filename;
        unless ($filename) {
            log_warn("Skipped saving history since filename not defined");
            return;
        }
        log_trace("Saving history to %s ...", $filename);
        open(my $fh, '>', $filename)
            or die "Can't open history file $filename for writing: $!\n";
        print $fh "$_\n" for grep { length } $self->{term}->GetHistory;
        close $fh or die "Can't close history file $filename: $!\n";
    }
}

sub postloop {
    my $self = shift;
    print "\n";
    $self->save_history;
}

sub prompt_str {
    my $self = shift;
    join(
        "",
        $self->colorize("riap", "4169e1"), " ", # royal blue
        $self->colorize($self->state("pwd"), "2e8b57"), " ", # seagreen
        "> ",
    );
}

sub _riap_set_copts {
    my $self = shift;
    return {
        user     => $self->setting('user'),
        password => $self->setting('password'),
    };
}

sub riap_parse_url {
    my ($self, $url) = @_;
    my $copts = $self->_riap_set_copts;
    $self->{_pa}->parse_url($url, $copts);
}

sub riap_request {
    my ($self, $action, $uri, $extra0) = @_;
    my $copts = $self->_riap_set_copts;

    my $surl = $self->state('server_url');

    my $extra = { %{ $extra0 // {} } };
    $extra->{uri} = $uri;

    my $show = $self->{_in_completion} ?
        $self->setting("debug_riap") && $self->setting("debug_completion") :
            $self->setting("debug_riap");

    if ($show) {
        say "DEBUG: Riap request: $action => $surl ".
            $self->json_encode($extra);
    }
    my $res;
    my $cache_key = $self->json_encode({action=>$action, %$extra});
    # we only want to cache some actions
    if ($action =~ /\A(info|list|meta|child_metas)\z/ &&
            ($res = $self->{_cache}->get($cache_key))) {
        # cache hit
        if ($show) {
            say "DEBUG: Riap response (from cache): $action => $surl ".
                $res;
        }
        $res = $self->json_decode($res);
    } else {
        # cache miss, get from server
        $res  = $self->{_pa}->request($action, $surl, $extra, $copts);
        if ($show) {
            say "DEBUG: Riap response: ".$self->json_encode($res);
        }
        if ($self->setting('cache_period')) {
            $self->{_cache}->set($cache_key, $self->json_encode($res),
                                 $self->setting('cache_period')." s");



( run in 0.450 second using v1.01-cache-2.11-cpan-0b5f733616e )