Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 71d09f6155
Fetching contributors…

Cannot retrieve contributors at this time

executable file 266 lines (209 sloc) 6.874 kb
#!/usr/bin/perl
our $APP = 'clipbored';
our $VERSION = '1.2.4';
use strict;
use Getopt::Long;
use Pod::Usage;
use File::Path 'mkpath';
my $xsel_log = clip_location();
my $pidfile = '/tmp/clipbored.pid';
my($opt_no_daemon, $opt_x_buffer) = (undef, lc($ENV{CLIPBORED_X_SELECTION}));
if(!defined($opt_x_buffer)) {
$opt_x_buffer = 'primary';
}
my($opt_no_daemon) = undef;
GetOptions(
'no-daemon' => \$opt_no_daemon,
'kill' => \&killkid,
'clear' => sub {
if(-e $xsel_log) {
open (my $fh, '>', $xsel_log) or die("Could not open $xsel_log: $!");
close($fh);
}
print "$xsel_log cleared\n";
exit(0);
},
'last:i' => \&lastlog,
'help' => sub {pod2usage(-verbose => 1); exit },
'man' => sub {pod2usage(-verbose => 3); exit },
'version' => sub { printf("%s v%s\n", $APP, $VERSION); exit },
);
if(-f $pidfile) {
print "clipbored is already running\n";
exit 1;
}
sync_cb();
sub lastlog {
shift;
my $wayback = shift;
$wayback = 25 unless(defined($wayback));
if($wayback < 1) {
$wayback = 25;
}
open(my $fh, '<', $xsel_log) or die("Could not open $xsel_log: $!");
my @records = <$fh>;
close($fh);
if(scalar(@records) < $wayback) {
$wayback = scalar(@records);
}
my $i = 0;
for(@records[scalar(@records) - $wayback .. scalar(@records) - 1]) {
printf("\e[1m%2d\e[0m %s", $i, $_);
$i++;
}
#FIXME collected since DATE
print "\e[1m" . scalar(@records) . "\e[0m selections collected \n";
exit(0);
}
sub sync_cb {
daemonize() unless(defined($opt_no_daemon));
while(1) {
my %selections = ();
chomp(my $current_selection = `/usr/bin/xclip -o -selection $opt_x_buffer`);
if(defined($current_selection)) {
open(my $r_xsel, '<', $xsel_log) or die("Cant open $xsel_log: $!");
chomp(my @selections = <$r_xsel>);
close($r_xsel);
$current_selection =~ s/\n/ /g; # newline hassle
map { $selections{$_} = undef } @selections;
if(exists($selections{$current_selection})) {
# DUPE
}
else {
open(my $a_xsel, '>>', $xsel_log) or die("Cant open $xsel_log: $!");
print $a_xsel $current_selection, "\n";
close($a_xsel);
print $current_selection, "\n" if(defined($opt_no_daemon));
}
}
sleep 2;
}
}
sub killkid {
open(my $fh, '<', $pidfile) or print "clipbored is not running\n" and exit(1);
my $target = <$fh>;
close($fh);
if(kill(9, $target)) {
print "clipbored with PID $target terminated\n";
}
else {
print "Could not kill $target: $!";
}
exit(0);
}
sub daemonize {
use POSIX 'setsid';
my $PID = fork();
exit(0) if($PID); #parent
exit(1) if(!defined($PID)); # out of resources
setsid();
$PID = fork();
exit(1) if(!defined($PID));
if($PID) { # parent
waitpid($PID, 0);
unlink($pidfile); # remove the lock when child have died
exit(0);
}
elsif($PID == 0) { # child
open(my $fh, '>', $pidfile) or die("Cant open $pidfile: $!");
print $fh $$;
close($fh);
open(STDOUT, '>', '/dev/null');
open(STDERR, '>', '/dev/null');
open(STDIN, '<', '/dev/null');
}
}
sub clip_location {
# File::Path exports a make_path function that would allow us to emulate
# mkdir -p behaviour. People running Perl < 5.10 didnt like that though.
my $dir = undef;
if(!defined($ENV{XDG_DATA_HOME}) or(!-d $ENV{XDG_DATA_HOME})) {
$dir = "$ENV{HOME}/.local";
}
else {
$dir = $ENV{XDG_DATA_HOME};
}
if(!-d $dir) {
mkpath($dir);
}
$dir .= "/clipbored";
if(!-d $dir) {
mkpath($dir);
}
$dir .= '/clips';
open(my $fh, '>>', $dir) or die($!);
close($fh);
return($dir);
}
__END__
=pod
=head1 NAME
clipbored - continuously collects all selections in Xorg's clipboard buffers
=head1 SYNOPSIS
clipbored [OPTIONS]
=head1 DESCRIPTION
B<clipbored> is a daemon that continuously grabs all non-duplicate selections
in the X.org clipboard buffers and writes them to a plaintext history file for
later use.
There are several scripts distributed with clipbored that'll use the history
file for different purposes.
=head2 Scripts
dmenurl - launch dmenu with all previously yanked URLs for you to select
from.
dmenuclip - launch dmenu listing all previously clipboarded content
=head1 OPTIONS
-l, --last show the n latest additions
-c, --clear clear all history
-n, --no-daemon do not detach from the shell
-k, --kill kill a running clipbored session
-h, --help show this help
-m, --man display the manual
-v, --version show version info
=head1 ENVIRONMENT
The history file location is $XDG_DATA_HOME/clipbored/clips
The X selection to use can be specified by setting the B<CLIPBORED_X_SELECTION>
environment variable.
If unset, or set to I<primary> , text is grabbed from the B<XA_PRIMARY> buffer.
When text is selected with the mouse, or piped through xclip/xsel with zero
arguments, it ends up here. This is most likely what you want.
If set to I<clipboard>, text is grabbed from the B<XA_CLIPBOARD> buffer. Data
ends up in this buffer when an explicit action is taken to cut/copy text; used
in many GUI environments.
To the best of my knowledge, the I<secondary> buffer is rarely used at all.
The helper scripts can read properties from environment variables.
These are recognized:
CLIPBORED_DMENU_LISTMODE regular/vertical
CLIPBORED_DMENU_NORMAL_FG foreground color in HEX
CLIPBORED_DMENU_NORMAL_BG background color in HEX
CLIPBORED_DMENU_SELECT_FG selected item background color in HEX
CLIPBORED_DMENU_SELECT_BG selected item foreground color in HEX
CLIPBORED_DMENU_FONT font that will be used
CLIPBORED_DMENU_LINES how many lines that will be shown in vertical mode
CLIPBORED_X_SELECTION X buffer to use: primary, secondary, clipboard
=head1 AUTHOR
\ \ | / /
\ \ - /
\ | /
(O O)
( < )
(-=-)
Magnus Woldrich
CPAN ID: WOLDRICH
magnus@trapd00r.se
http://japh.se
=head1 CONTRIBUTORS
Markus Weimar suggested we should be able to pick the clipboard buffer to use.
Since I very rarely use any GUI applications, I wasn't aware of the fact that
when CTRL+C/CTRL+V etc is used, it goes into the XA_CLIPBOARD buffer instead of
the XA_PRIMARY, probably rendering clipbored somewhat useless to the users using
these types of applications. :)
=head1 REPORTING BUGS
Report bugs to L<trapd00r@trapd00r.se> or L<use the issue tracker|http://github.com/trapd00r/clipbored/issues>.
clipbored home page: L<http://github.com/trapd00r/clipbored/>
=head1 COPYRIGHT
Copyright 2010, 2011 the B<clipbored>s L</AUTHOR> and L</CONTRIBUTORS> as listed
above.
=head1 LICENSE
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut
Jump to Line
Something went wrong with that request. Please try again.