AnyEvent-I3

 view release on metacpan or  search on metacpan

lib/AnyEvent/I3.pm  view on Meta::CPAN

            });
        }
    })->recv->{success} or die "Error subscribing to events";

    AE::cv->recv

=head1 EXPORT

=head2 $i3 = i3([ $path ]);

Creates a new C<AnyEvent::I3> object and returns it.

C<path> is an optional path of the UNIX socket to connect to. It is strongly
advised to NOT specify this unless you're absolutely sure you need it.
C<AnyEvent::I3> will automatically figure it out by querying the running i3
instance on the current DISPLAY which is almost always what you want.

=head1 SUBROUTINES/METHODS

=cut

use Exporter qw(import);
use base 'Exporter';

our @EXPORT = qw(i3);

use constant TYPE_RUN_COMMAND => 0;
use constant TYPE_COMMAND => 0;
use constant TYPE_GET_WORKSPACES => 1;
use constant TYPE_SUBSCRIBE => 2;
use constant TYPE_GET_OUTPUTS => 3;
use constant TYPE_GET_TREE => 4;
use constant TYPE_GET_MARKS => 5;
use constant TYPE_GET_BAR_CONFIG => 6;
use constant TYPE_GET_VERSION => 7;
use constant TYPE_GET_BINDING_MODES => 8;
use constant TYPE_GET_CONFIG => 9;
use constant TYPE_SEND_TICK => 10;
use constant TYPE_SYNC => 11;
use constant TYPE_GET_BINDING_STATE => 12;

our %EXPORT_TAGS = ( 'all' => [
    qw(i3 TYPE_RUN_COMMAND TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS
       TYPE_GET_TREE TYPE_GET_MARKS TYPE_GET_BAR_CONFIG TYPE_GET_VERSION
       TYPE_GET_BINDING_MODES TYPE_GET_CONFIG TYPE_SEND_TICK TYPE_SYNC
       TYPE_GET_BINDING_STATE)
] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );

my $magic = "i3-ipc";

# TODO: auto-generate this from the header file? (i3/ipc.h)
my $event_mask = (1 << 31);
my %events = (
    workspace => ($event_mask | 0),
    output => ($event_mask | 1),
    mode => ($event_mask | 2),
    window => ($event_mask | 3),
    barconfig_update => ($event_mask | 4),
    binding => ($event_mask | 5),
    shutdown => ($event_mask | 6),
    tick => ($event_mask | 7),
    _error => 0xFFFFFFFF,
);

sub i3 {
    AnyEvent::I3->new(@_)
}

# Calls i3, even when running in taint mode.
sub _call_i3 {
    my ($args) = @_;

    my $path_tainted = tainted($ENV{PATH});
    # This effectively circumvents taint mode checking for $ENV{PATH}. We
    # do this because users might specify PATH explicitly to call i3 in a
    # custom location (think ~/.bin/).
    (local $ENV{PATH}) = ($ENV{PATH} =~ /(.*)/);

    # In taint mode, we also need to remove all relative directories from
    # PATH (like . or ../bin). We only do this in taint mode and warn the
    # user, since this might break a real-world use case for some people.
    if ($path_tainted) {
        my @dirs = split /:/, $ENV{PATH};
        my @filtered = grep !/^\./, @dirs;
        if (scalar @dirs != scalar @filtered) {
            $ENV{PATH} = join ':', @filtered;
            warn qq|Removed relative directories from PATH because you | .
                 qq|are running Perl with taint mode enabled. Remove -T | .
                 qq|to be able to use relative directories in PATH. | .
                 qq|New PATH is "$ENV{PATH}"|;
        }
    }
    # Otherwise the qx() operator wont work:
    delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
    chomp(my $result = qx(i3 $args));
    # Circumventing taint mode again: the socket can be anywhere on the
    # system and that’s okay.
    if ($result =~ /^([^\0]+)$/) {
        return $1;
    }

    warn "Calling i3 $args failed. Is DISPLAY set and is i3 in your PATH?";
    return undef;
}

=head2 $i3 = AnyEvent::I3->new([ $path ])

Creates a new C<AnyEvent::I3> object and returns it.

C<path> is an optional path of the UNIX socket to connect to. It is strongly
advised to NOT specify this unless you're absolutely sure you need it.
C<AnyEvent::I3> will automatically figure it out by querying the running i3
instance on the current DISPLAY which is almost always what you want.

=cut
sub new {
    my ($class, $path) = @_;

    $path = _call_i3('--get-socketpath') unless $path;



( run in 0.751 second using v1.01-cache-2.11-cpan-2398b32b56e )