diff options
Diffstat (limited to 'xcleanpaste')
-rwxr-xr-x | xcleanpaste | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/xcleanpaste b/xcleanpaste new file mode 100755 index 0000000..c122002 --- /dev/null +++ b/xcleanpaste @@ -0,0 +1,153 @@ +#!/usr/bin/perl -w + +=pod + +=head1 NAME + +xcleanpaste - join multi-line copy/paste into one long line + +=head1 SYNOPSIS + +B<xcleanpaste> [-n] [-u] [-e<line-ending>] [-v] [xsel-options] + +=head1 DESCRIPTION + +"Cleans" the X selection buffer: trims whitespace from the start +and end of every line, replaces all newlines with spaces, replaces +all tabs with 3 spaces each. Result is written back to the selection +buffer, where you can paste it into whatever application you want. + +This is useful even for single-line pastes: it removes tabs and any +newline at the end, so e.g. copying a command from a browser into the +shell won't trigger tab-completion or execute the command immediately. + +The selection buffer is read/written using xsel, which must be +installed and available on your PATH. + +xcleanpaste is best used by binding to a key using xbindkeys or +similar, though you can run it from the shell too. + +If you're using keybinding, you probably want at least separate keys +for xcleanpaste with no options and xcleanpaste with the -u option +(URL cleaner; see below). + +=head1 OPTIONS + +=over 4 + +=item B<-e><line-ending> + +Replace line endings with the given string rather than a space. Don't +use a space between the -e and the ending. Beware of shell quoting +rules. + +=item B<-n> + +Replace line endings with the string " \n " rather than a space. This is +space, backslash, lowercase n, space. Equivalent to B<-e ' \n '>. + +=item B<-u> + +Remove CGI arguments from any URLs found in the buffer. Some sites +including tracking info, e.g. https://site.blah/stuff?sessionID=12345, +which you shouldn't be pasting into anything others can see (e.g. IRC +or emails). + +=item B<-v> + +Verbose mode. Shows lines read and written from the xsel instances on +stderr. Not much use with xbindkeys though. + +=back + +Any other arguments are passed to xsel. This is probably only useful +for xsel's -p/-s/-b options (see xsel man page). + +=head1 EXAMPLE + +In B<~/.xbindkeys>: + + "xcleanpaste &" + Control+Alt + period + + "xcleanpaste -u &" + Control+Alt + slash + +If you copy these three lines: + + This is + a long URL: + https://long.url?with=lots&of=arguments + +Then press Ctrl+Alt+Period, then paste into some window, you will get: + + This is a long URL: https://long.url?with=lots&of=arguments + +If you instead press Ctrl+Alt+Slash, you'll get: + + This is a long URL: https://long.url + +=head1 AUTHOR + +xcleanpaste was written by B. Watson <yalhcru@gmail.com> and released +under the WTFPL: Do WTF you want with this. + +=cut + +( $SELF = $0 ) =~ s,.*/,,; + +@xselargs = (); +$line_ends = " "; +$url_clean = $verbose = 0; + +for(@ARGV) { + if(/^-?-h(?:elp)/) { + exec "perldoc $0"; + exit 1; # if the exec failed + } elsif(/^-v/) { + $verbose++; + } elsif(/^-n/) { + $line_ends = " \\n "; + } elsif(/^-u/) { + $url_clean = 1; + } elsif(/^-e(.*)$/) { + if(!defined($1) || $1 eq "") { + die("$SELF: no space allowed between -e option and its argument\n"); + } + $line_ends = $1; + } else { + push @xselargs, $_; + } +} + +$xsel_extra_args = join(" ", @xselargs); +warn "$SELF: xsel arguments: \"$xsel_extra_args\"\n" if $verbose; + +# We have to read the entire output of xsel -o into memory before +# spawning the xsel -i, because otherwise the 2nd xsel will obliterate +# the selection buffer the first one's still trying to read from. +open my $in, "xsel -o $xsel_extra_args|" or die $!; +while(<$in>) { + chomp; + warn "$SELF: read line $.: $_\n" if $verbose; + s,\s+$,,; # remove any trailing whitespace + s,^\s+,,; # remove any leading whitespace + s,[\r\n], ,g; # replace all CR or LF with a single space + s,\t, ,g; # replace all tabs with 3 spaces + if($url_clean) { + # get rid of ? and anything after it, in anything that looks like a URL + s,(https?:\/\/[^?\s]*)\?\S+,$1,g; + } + s/\S$/$&$line_ends/; # our ending LF became a space above; make it + # whatever the line ending is supposed to be + push @lines, $_; +} +close $in; + +$output = join("", @lines); +$output =~ s/\s+$//; # trim trailing whitespace from last line only +warn "$SELF: writing: $output\n" if $verbose; + +open my $out, "|xsel -i $xsel_extra_args" or die $!; +print $out $output; +close $out; |