App-BCVI
view release on metacpan or search on metacpan
lib/App/BCVI/Plugins.pod view on Meta::CPAN
=item *
add new back-channel commands (and add code to implement those commands in
the listener process)
=item *
modify almost any existing functionality of C<bcvi> (including removing
functionality)
=item *
modify both the server (listener) and/or the client
=back
Ideally you should be able to customise the behaviour of C<bcvi> in pretty
much any way you want without needing to edit the C<bcvi> script itself.
=head1 A SIMPLE EXAMPLE
Here's a silly plugin (that no sane person would ever want to use) which
overrides the 'vi' command handler and instead of launching C<gvim> it launches
C<gedit> (the GNOME text editor) - I did warn you it was a silly example:
package App::BCVI::Gedit;
use strict;
use warnings;
sub execute_vi {
my($self) = @_;
my $alias = $self->calling_host();
my @files = map { "sftp://${alias}$_" } $self->get_filenames();
system('gedit', '--', @files);
}
App::BCVI->hook_server_class();
1;
This file should be saved as F<$HOME/.config/bcvi/Gedit.pm>. Let's go through
it line-by-line.
Each plugin must have a unique package name. The App::BCVI namespace is there
for plugins to use. By convention, the filename should match the last part of
the package name, with '.pm' appended.
The C<use strict;> and C<use warnings;> are good practice in any Perl module.
The C<execute_vi> subroutine was copy/pasted from the C<bcvi> script itself
and then modified to work with C<gedit> rather than C<gvim>.
The C<hook_server_class> line is a method call that pushes this class onto the
inheritance chain for the object class that implements the listener process.
When the listener process calls C<execute_vi> in response to a request from a
client, our method is called instead of the standard method. In some plugins,
it might make sense to delegate to the standard method using the syntax
C<< $self->SUPER::execute_vi(@args) >>, but in our case we're replacing the
standard method rather than augmenting it.
=head1 PLUGIN LOADING
Plugin files are never loaded from anywhere except the user's BCVI config
directory. In particular, C<bcvi> never loads any modules from the system
F<lib/App/BCVI> directory. If you get plugin modules from CPAN, you'll need
to copy the .pm files into your plugin directory (or possibly symlink to the
.pm file in the system lib directory).
Some plugins enhance the listener process and therefore only need to be
installed on your workstation. Other plugins enhance the client so they need
to be installed on the hosts where you use bcvi. Client-side plugins can
register themselves to be included in the set of files that get deployed to a
host when you run C<< bcvi --install HOSTNAME >>.
=head1 CLASS HOOKS
The BCVI application is built from four classes:
=over 4
=item B<App::BCVI::Server>
Implements the listener process as a forking server. Listens on a socket, when
an incoming connection is received, a child process is forked off to handle it.
=item B<App::BCVI::Client>
Implements the client process which establishes a TCP connection to the
listener process, sends a request and waits for a response.
=item B<App::BCVI>
A base class implements common methods used by both the client and the server.
=item B<App::BCVI::POD>
A helper class used by both the client and the server to render POD to text
in response to the C<--help> option.
=back
A plugin can push its package name onto the inheritance chain for the server
by calling:
App::BCVI->hook_server_class();
or for the client by calling
App::BCVI->hook_client_class();
There are currently no hook methods for either the base class or the POD class
because that didn't seem very useful (just ask if you really need this).
The example plugin above had a package name of C<App::BCVI::Gedit> and it
called C<hook_server_class()>. This has two effects:
=over 4
( run in 1.984 second using v1.01-cache-2.11-cpan-5b529ec07f3 )