Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Clipboard transform keys

by PhilHibbs (Hermit)
on Aug 05, 2003 at 19:01 UTC ( #281123=CUFP: print w/ replies, xml ) Need Help??

I use NT4 and Win2K at work. My main use for Perl is as a productivity tool, and a lot of the scripts I use take the text out of the Win32::Clipboard, do something to it, then put it back. I then make a shortcut (.lnk) to the script, put it in Accessories in my Start menu, and assign a double bucky to it. I can then run my transforms by copying the source info into the clipboard, hit the magic key, watch the black box of a command prompt flicker in and out of view (sometimes takes a second on NT, much quicker on Win2K), then paste the results. The most recent one I did was this:
sub X { return X($_[0]); } sub x { return sprintf("%x",$_[0]); } my $CLIP = Win32::Clipboard(); my $text = $CLIP->GetText(); my $result; print '$_='.$text."\n"; eval('$_='.$text); print $_."\n"; $CLIP->Set($_);
Then I can build up mathematical equations in my text editor, and evaluate them without having to run Calculator and alt-tab back and forth all the time. Update: Added X and x functions to convert to hex. Other tricks include converting a vertical list of values into a comma-separated quoted list that breaks after 72 characters, trim all trailing spaces, adding <href=" to the start and "></a> to the end (I've used that one a couple of times in this writeup), convert < and > to &lt; and &gt; (and I'm considering writing one that prepends and appends <code> and </code>!), and the one that I use perhaps the most, does nothing apart from read the clipboard, and write it back again. Why? Because it throws away any formatting. If you right-click and copy a URI in IE, and paste it into Outlook, it becomes a .URL attachment. If I hit the appropriate key, then it gets pasted in as plain text. If I hit another key, it gets wrapped in a <a href=""></a> tag set ready for pasting into an HTML file, a Slashdot comment, or a Perl Monks writeup. I just wrote the <CODE></CODE> wrapper, it took me exactly one minute to write it (excluding the later addition of the <code></code> protection), make the shortcut, move it into the Start menu, and assign a key to it.

The code looks like this (it's a Windows NT command file, for those lucky enough to have never encountered one before):

@rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use Win32::Clipboard; my $CLIP = Win32::Clipboard(); my $text = $CLIP->GetText; $text =~ s|</ code>|</</ code><code>code>|gx; $CLIP->Set('<<i></i>code>'.$text.'<'.'/code>'); __END__ :endofperl
At first I was breaking the </CODE> by inserting </CODE><CODE> inside it, but it appears that if there are line breaks within the <CODE></CODE> block, then it is assumed that there should be one at the end as well. Then I used <pre> instead of <code> in this writeup in order to get that last </CODE> to display correctly. Now I just change the original perl code so that it no longer contains </code>.

My head really hurts.

In addition, of course, I write the occasional I/O filter for text file transformations or greps, but there's nothing innovative about them.

Update: Is there a way to do this kind of thing in Linux?

Comment on Clipboard transform keys
Select or Download Code
Re: Clipboard transform keys
by halley (Prior) on Aug 06, 2003 at 16:42 UTC
    Nice polyglot. It's extra-defensive. In the way of explanation, since not all Windows command scripts are so complicated,
    @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 YOUR PERL CODE HERE; __END__ :endofperl
    This can be run as a Windows command file itself, or as a Perl script directly, and the syntax hacks are designed to fool both interpreters into ignoring the parts intended for the other.

    In perl, lines 1..5 are @rem = '...'; and the resulting array is otherwise ignored. In Windows script, that's five separate commands: (1) an unechoed remark @rem, (2) an unechoed command to turn off further automatic echoes @echo off, (3) an invocation of perl on the script itself with its first nine arguments, (4) a command to skip any other lines until one matching /^:endofperl/, and another unechoed remark @rem. The first line, as a bonus, suggests the file should be edited in perl-mode for some smart editors.

    The perl -x tells perl to skip anything ahead of the shebang line matching /^\#\!/. This is only seen when the command script invokes Perl. It shouldn't be necessary since the @rem=''; trick should armor these lines, but it's defensive. The odd "%~dpnx0" reconstructs the %0 variable explicitly with all possible components: drive, path, name, extension.

    The #line 8 trick aligns perl's error-reporting features with the actual polyglot script's lines. Otherwise, any errors would be reported, thanks to the perl -x as numbered relative to the shebang line.

    Of course, perl quits reading at the __END__ token, so anything following is ignored by perl, but the last line is the aforementioned target for the command script's goto endofperl command.

    --
    [ e d @ h a l l e y . c c ]

      I wasn't sure what the -S and -x did, they were there in the original that I nicked (runperl.bat from the ActiveState install). You don't mention is what the -S does, which I've now looked up - it tells perl to search the path. I've removed it because I actually don't want that happening.
        Why do you need that batchfile wrapper? Set up your .LNK to run perl.exe with the script name as an argument, rather than requiring the target to be something that directly executes.

        For that matter, why doesn't a lnk to a .pl file do the right thing anyway, just like double-clicking on the .pl file would?

Re: Clipboard transform keys
by Freddo (Acolyte) on Aug 12, 2003 at 00:33 UTC
    I can then run my transforms by copying the source info into the clipboard, hit the magic key, watch the black box of a command prompt flicker in and out of view (sometimes takes a second on NT, much quicker on Win2K), then paste the results.

    If you're running with ActiveState perl, there's probably a registry entries for *.wsf files (look in the examples directory of perl). With the wsf you can get rid of the cmd box. Simply do:
    <Job ID="MyClipCode"> <script language=PerlScript> # Your perl code here </script> </Job>
    and voila! (but now strict and warning wont display too much help). update: i wrecked the whole thing with the code tags and pressed submit instead of preview... :o)
      I like to test the script in a Command Prompt, and often leave the debug output in place in case I feed my script something that I didn't anticipate. I'll give it a go though, I might find a middle-ground solution. I might even write and test them as raw perl scripts, and have another process that generates the .wsf file.
      Without the wsh stuff, you could run a regular perl file with the wperl.exe version of the interpreter instead. Define a file extension different from .pl or .perl (say, .wperl) if ActiveState didn't do that already.
Re: Clipboard transform keys
by phildog (Novice) on Aug 14, 2003 at 16:55 UTC
    Nice! Can you post the href transform code in this thread as well?
      Here's the script that transforms an URI into a HTML link:
      @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use HTML::Entities; use Win32::Clipboard; my $CLIP = Win32::Clipboard(); my $text = $CLIP->GetText; if (substr($text,0,1) ne '<') { chomp $text; $text = encode_entities($text); $CLIP->Set('<a href="'.$text.'"></a>'); } __END__ :endofperl
      Update:Uses HTML::Entities to translate & to &amp; etc.
Clipboard transform key: Text to HTML for PerlMonks
by PhilHibbs (Hermit) on Aug 19, 2003 at 18:08 UTC
    Here is another clipboard transform that I use. It translates plain text to HTML markup for special characters, and is enhanced for PerlMonks with [ and ] handling (there, I just used it). I call it "clipmonk.cmd", and I bind it to Ctrl-Shift-M.
    Update: Added L~R, ()}{ and s_t translation
    @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use HTML::Entities; use Win32::Clipboard; my $CLIP = Win32::Clipboard(); my $text = $CLIP->GetText; $text = encode_entities($text); $text =~ s|\[|\&#091;|g; $text =~ s|\]|\&#093;|g; $text =~ s/L~R/[Limbic~Region|L~R]/g; $text =~ s/\(\)}{/[(-+-)bsidian }{eat|()}{]/g; $text =~ s/s_t/[submersible_toaster|s_t]/g; $CLIP->Set($text); __END__ :endofperl
Clipboard transform key: Comma-separated list maker
by PhilHibbs (Hermit) on Aug 19, 2003 at 18:20 UTC
    Here is another clipboard transform that I use. It transforms a \n-separated list into a comma-separated list with " around each item and ( and ) around the list, wrapped to 72 columns (for use in a 3270 emulator). It doesn't use text:wrap, because a string might contain a space, and be wrapped inappropriately. I call it "cqlist.cmd" and bind it to Ctrl-Shift-'.
    @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use Win32::Clipboard; my $CLIP = Win32::Clipboard(); my ($output, $lastline) = ("", "("); foreach( split m[\x0d\x0a?|\x0a\x0d?], $CLIP->GetText ) { (my $quoted = $_) =~ s/'/''/g; $quoted = qq['$quoted', ]; if( $lastline ne "" and length($lastline) + length($quoted) > 72 ) +{ chop $lastline; # remove trailing space $output .= $lastline . "\n"; $lastline = ""; } $lastline .= $quoted; } $lastline =~ s|, \z|)|; # convert last ", " to a ")" $output .= $lastline; $output =~ s|\n|\x0d\x0a|g; # convert perlish \n to windows CRLF. print $output; $CLIP->Set($output); __END__ :endofperl
Re: Clipboard transform keys
by PhilHibbs (Hermit) on Sep 16, 2003 at 12:46 UTC
    Here is another clipboard transform that I use. It splits the clipboard text in half and adds the second half to the end of the first half line-by-line, so this:
     a
     b
     c
     d
     e
     f
    becodes this:
     a d
     b e
     c f
    I call it "clipjoin.cmd" and bind it to Ctrl-Shift-J.
    @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict;0 use warnings; use Win32::Clipboard; my $CLIP = Win32::Clipboard(); my $text = $CLIP->GetText; my @text = split /\r\n/,$text; my $lines = scalar @text; my $halflines = $lines/2; for (my $i=0; $i<$lines/2; ++$i) { $text[$i] .= $text[$i+$halflines]; } @text = @text[0...$halflines-1]; $text = join "\r\n", @text; $text .= "\r\n"; $CLIP->Set($text); __END__ :endofperl
Clipboard transform key: scraper_help
by PhilHibbs (Hermit) on Nov 13, 2003 at 12:29 UTC
    This one isn't bound to a keypress, it runs in the background and watches for clipboard changes. It collates screen captures from a mainframe terminal, and stitches them side-by-side. I normally do a de-dupe blank columns afterwards. You have to give it a marker (I use __END__) to know when to finish and write the text back to the clipboard.
    @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use Win32::Clipboard; my $CLIP = Win32::Clipboard(); my $not_finished = 1; my @data = ''; $CLIP->WaitForChange(); while ( $not_finished ) { $CLIP->WaitForChange(); print "changed\n"; $_ = $CLIP->GetText; s|\x0d\x0a|\x0a|g; # remove MS line-ends if ( scalar @data == 0 ) { @data = split "\n", $_; } else { my $line = 0; for ( split "\n", $_ ) { $data[$line++] .= $_; } } if ( m|__END__| ) { $not_finished = 0; # Finished after this block! } } $CLIP->Set(join("\n",@data)); __END__ :endofperl
Clipboard transform key: de-dupe blank columns
by PhilHibbs (Hermit) on Nov 13, 2003 at 12:34 UTC
    This one searches the clipboard text for blank columns, and removes them if there are two or more adjacent. I use it to tidy up captured screens, especially those that have been stitched together.
    @rem = '--*-Perl-*-- @echo off perl -x -S "%~dpnx0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use Win32::Clipboard; use Text::Orientation; my $CLIP = Win32::Clipboard(); my $rot = Text::Orientation->new( TEXT => $CLIP->GetText ); $_ = $rot->transpose(); s|\x0d\x0a|\x0a|g; s/\n( +)\n +\n/\n$1\n/g while /\n( +)\n +\n/; $rot = Text::Orientation->new( TEXT => $_ ); $CLIP->Set( $rot->transpose() ); __END__ :endofperl
Re: Clipboard transform keys
by Anonymous Monk on Nov 13, 2003 at 12:48 UTC
    pl2bat is your friend
    E:\>more hi.pl print "hi\n"; E:\>pl2bat hi.pl E:\>hi hi E:\>more hi.bat @rem = '--*-Perl-*-- @echo off if "%OS%" == "Windows_NT" goto WinNT perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl :WinNT perl -x -S %0 %* if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl if %errorlevel% == 9009 echo You do not have Perl in your PATH. if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul goto endofperl @rem '; #!perl #line 15 print "hi\n"; __END__ :endofperl
      I have a few variants of my own, for different perl installations. Some machines in the office have 5.00502 installed but not in the path, so I add a handful of extra lines that handle this. Also, some of my perl batches are self-logging.
Advanced Clipboard transform keys
by Koosemose (Pilgrim) on Mar 03, 2004 at 10:01 UTC

    For extra added fun, and laziness, add the Win32::Guitest Module into the mixture. That way you can use SendKeys() to send a copy and or paste, and only have to push your double bucky.

    For this to work properly, you need to either add an extension for windowless perl scripts (i.e. using wperl) or change the batch file to call on wperl.

    I have noticed a few things in Win32::Clipboard and Win32::GUITest that can bite you if you're not careful, first, it doesn't get the magic line-break translation that files and other IO operations do, so your linebreaks (mine were at least) will likely be \r\n instead of just \n. It may or may not matter according to where you are putting the output (my Email client doesn't much like just one or the other). Also apparenly, chomp only cut's off the \n, so you've gotta watch for that. And in ::GUITest, with the Sendkeys() you have to use lowercase for ctrl+c and ctrl+v, else you may end up not getting the effect you expected.

    And now, a sample piece of code for making ordered lists, nice and easy, it's even set up so you can run it over pieces of text that have already been tagged, so you can make nested lists.

    #!perl use Win32::GuiTest qw(SendKeys); use win32::Clipboard; my $CLIP = Win32::Clipboard(); SendKeys("^c"); my $alter = $CLIP->Get(); my @alter = split /\r\n/, $alter; foreach (@alter) { if (/\W/) { $_ = "<li> $_ </li>" if !/<li>/; $_ .= "\r\n"; } else { $_="\r\n"; } } $alter = join("",@alter); $alter = "<ol>\r\n".$alter."</ol>"; $CLIP->Set($alter); SendKeys("^v");
Re: Clipboard transform keys
by PhilHibbs (Hermit) on Jun 25, 2004 at 11:16 UTC
    I have just discovered http://unxutils.sourceforge.net/ which, in addition to the various GNU utilities such as grep, diff, sed, etc., comes with pclip.exe and gclip.exe that output and input the clipboard to/from stdout and stdin respectively. This means you can chain a text processing utility in between, such as pclip | sed "s/string1/string2/g" | gclip.

    Although I've never been a Unix user, I truly appreciate the power of chaining text processing comands like this, and might well convert my clipboard processors to stdin/stdout processors, and have the shortcut run a piped command chain like this.

Re: Clipboard transform keys
by PhilHibbs (Hermit) on Aug 16, 2004 at 11:39 UTC
    Here is the latest version of my calculator script. It treats each line of input, stopping on an '=' character, as a separate calculation, and appends the answer after an '=' character. That way you can easily amend the calculation and perform it again.
    @rem = '--*-Perl-*-- @echo off perl "%~dpnx0" %* goto endofperl @rem '; #!perl #line 8 use strict; use warnings; use Win32::Clipboard; sub X { return sprintf("%x",$_[0]); } sub x { return X($_[0]); } my $CLIP = Win32::Clipboard(); my $text = $CLIP->GetText(); my @text = split /\n/, $text; my @results = (); for ( @text ) { s[\x0a][]; s[\x0d][]; s/([^=]+)=.+/$1/; # trim after '=' s/(^|[^0-9\.])0+/$1/g; # remove leading zeros (don't want octal) print "\$_.=' =\t'.($_)\n"; eval("\$_.=' =\t'.($_)"); print " = $_\n"; push @results, $_; } $CLIP->Set(join("\n",@results)."\n"); __END__ 4*3 11-4*2 010+020+030 = 61 x(123) = 7b :endofperl

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://281123]
Approved by Corion
Front-paged by ybiC
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (10)
As of 2014-07-28 05:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (186 votes), past polls