App-BashHistoryUtils

 view release on metacpan or  search on metacpan

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


sub _do {
    require Bash::History::Read;
    require Capture::Tiny;
    require Cwd;

    my $which = shift;
    my %args = @_;

    my $histfile = $args{histfile};
    return [412, "Can't find '$histfile': $!"] unless -f $histfile;
    my $realhistfile = Cwd::realpath($args{histfile})
        or return [412, "Can't find realpath of '$histfile': $!"];

    if ($which eq 'grep' && !defined($args{pattern})) {
        return [400, "Missing required argument: pattern"];
    }

    my $pat;
    if (defined $args{pattern}) {
        if ($args{ignore_case}) {
            $pat = qr/$args{pattern}/i;
        } else {
            $pat = qr/$args{pattern}/;
        }
    }

    my $now = time;

    my $code;
    if ($which eq 'each') {
        $code = eval "package main; no strict; sub { $args{code} }";
        die if $@;
    } else {
        $code = sub {
            if (defined($args{max_age}) &&
                    $main::TS < $now-$args{max_age}) {
                $main::PRINT = 0;
            }
            if (defined($args{min_age}) &&
                    $main::TS > $now-$args{min_age}) {
                $main::PRINT = 0;
            }
            if ($pat && $_ =~ $pat) {
                $main::PRINT = 0;
            }

            if ($which eq 'grep') {
                $main::PRINT = !$main::PRINT;
            }
            if ($args{invert_match}) {
                $main::PRINT = !$main::PRINT;
            }

            if ($args{strip_timestamp}) {
                undef $main::TS;
            }
        };
    }

    local @ARGV = ($histfile);
    my $stdout = Capture::Tiny::capture_stdout(
        sub {
            Bash::History::Read::each_hist($code);
        }
    );

    if ($which eq 'grep' ||
            $which eq 'each' ||
            $which eq 'delete' && ($args{-dry_run} || !$args{inplace})) {
        return [200,"OK", $stdout, {'cmdline.skip_format'=>1}];
    } elsif ($which eq 'delete') {
        require File::Temp;
        my ($tempfh, $tempfile) = File::Temp::tempfile(template => "${realhistfile}XXXXXX");
        open my($fh), ">", $tempfile
            or return [500, "Can't open temporary file '$tempfile': $!"];

        print $fh $stdout
            or return [500, "Can't write (1) to temporary file '$tempfile': $!"];

        close $fh
            or return [500, "Can't write (2) to temporary file '$tempfile': $!"];

        rename $realhistfile, "$realhistfile~"
            or warn "Can't move '$realhistfile' to '$realhistfile~': $!";
        rename $tempfile, $realhistfile
            or return [500, "Can't replace temporary file '$tempfile' to '$realhistfile': $!"];
    }

    [200,"OK"];
}

$SPEC{grep_bash_history_entries} = {
    v => 1.1,
    summary => 'Show matching entries from bash history file',
    args => {
        %arg_histfile,
        %args_filtering,
        %args_formatting,
    },
};
sub grep_bash_history_entries {
    _do('grep', @_);
}

$SPEC{delete_bash_history_entries} = {
    v => 1.1,
    summary => 'Delete matching entries from bash history file',
    args => {
        %arg_histfile,
        %args_filtering,
        %args_formatting,
        inplace => {
            summary => 'Replace original bash history file',
            schema => ['bool', is=>1],
        },
    },
    features => {
        dry_run => 1,
    },
};

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 1.522 second using v1.00-cache-2.02-grep-82fe00e-cpan-cec75d87357c )