[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl-Scribes] "Basic Perl Filters in BBEdit" Column



Minutes of "Basic Perl Filters in BBEdit" Column as/at 10 April

<html><body>
<h2>Basic Perl Filters in BBEdit</h2>

Back in issue #7, Vicki Brown wrote about her "<a
href='http://www.perlmonth.com/columns/mac_perl/mac_perl.html?issue=7'>MacPe

rl Development Environment</a>" .  For the most part, what she describes
there is a typical setup for a serious MacPerler.  In her article Vicki
covered, among other things, BBEdit, from <a
href="http://www.barebones.com/">Bare Bones Software </a>.  As of version
5.1, BBEdit has MacPerl support built in.  Older versions used a plug-in
module for roughly the same functionality.  However having built-in
support
means MORE than just the ability to use BBEdit as a text-editor and front
end for MacPerl.

BBEdit allows you to create "Perl Filters": scripts to which a text
selection, or even an entire document may be passed, which then return
their results to BBEdit. BBEdit isn't the only Mac text-editor with
built-in Perl support, and neither is it the only editor which lets you
use
Perl scripts as text filters.  <a href="http://alpha.olm.net/">Alpha</a>
has similar functionality and a very vocal following.  I'm hoping to
corral
one of those vocal followers into writing a column on the subject.

<h3>An Example One-Line Filter</h3>

For the most part, Perl Filters tend to be short (one or two line)
scripts,
which do various regular expression functions not possible with BBEdit's
own regex capability.  Frequently, you need to make multiple passes over a
document, or parse it in a way which isn't possible with regex alone, like
so:
<BR><BR>
#!perl -p <BR>
s/(\d+)-(\d+)/$1 > $2 ? "$1-$2" : join ', ', $1 .. $2/ge<BR><BR>

Alas, I'm not the author.  This came about as the result of one of the
frequent filter-generation sessions on the BBEdit-Talk[1] list. On a
Friday, someone blithely asked for a script which could parse a certain
set
of strictly formatted strings of numbers.  The problem was first
approached
using a rather convoluted AppleScript, which even the author concluded was
ugly.  Next, a Perler tried his hand.  Finally, Ronald Kimball stepped in,
reducing the Perl script to its most idiomatically concise form.  Ron
claims the result is again "ugly", but the original poster referred to it
as "inspirational".<BR>

Oh, and what does it do?  The answer is <a
href="http://search.barebones.com/action.lasso?-database=lists.fp3&-
layout=import&-response=%2ftalk%5flists%2fdetail.html&-recid=47440&-search
message"> here.</a>

<h3>Filters using Perl Modules</h3>

Are you lazy?  You just don't want to open your mail client to post mail?
You'd rather stay in your text-editor?  Well, so did Rory Campbell-Lange:<BR>

#!perl -w<BR>
# campbell-lange@easynet.co.uk (Rory Campbell-Lange)<BR>
# only barely modified from the example in<BR>
# the Mail::Send POD<BR>

require Mail::Send;<BR>

@allmail = <>;<BR>
$to = shift @allmail;<BR>
chomp $to;<BR>
$subject = shift @allmail;<BR>
chomp $subject;<BR>
$msg = new Mail::Send;<BR>
<BR>
$msg->to($to);<BR>
$msg->subject($subject);<BR>

$fh = $msg->open;<BR>
print $fh "@allmail";<BR>
$fh->close;
<BR>
Oh, but that doesn't handle MIME attachments you say?<BR>
<BR>
#!perl -w<BR>
# campbell-lange@easynet.co.uk (Rory Campbell-Lange)<BR>
# only barely modified from the example in<BR>
# the MIME::Lite POD<BR>

use MIME::Lite;<BR>
MIME::Lite->send('smtp', "mymail.example.org", Timeout=>200);<BR>

    my $to = shift;<BR>
    my $sub = shift;<BR>
    my $filetoattach = shift;<BR>
    my $filename = shift;<BR>
    my @message = @_;<BR>

  $msg = new MIME::Lite<BR>
    From     =>'me@mymail.co.uk',<BR>
    To       => $to,<BR>
    #Cc      => couldbeshift,<BR>
    Subject  => $sub,<BR>
    Type     =>'TEXT',<BR>
    Data     => @message,<BR>
    <BR>
  attach $msg<BR>
    Type     =>'image/gif',<BR>
    Path     => $filetoattch,<BR>
<BR>
    Encoding => 'base64',<BR>
    Filename => $filename;<BR>
<BR>
$msg->send;<BR>
<BR>
A sufficiently intrepid programmer could easily use this as the starting
point for a complete mail client, written as a BBEdit Perl Filter!<BR>

<h3>Filters with No Input</h3>

Nothing says that a "filter" has to take an input to produce an output.
This example creates a timestamp:<BR>

#!perl<BR>
 my ( $year, $month, $day, $hour, $min, $sec) = reverse((localtime)[0 ..
5]);<BR>
 printf('%04d:%02d:%02d
%02d:%02d:%02d',$year+1900,$month+1,$day,$hour,$min,$sec);<BR>
<BR>
I've done other scripts which do more complex things, such as generating
an
XML file, then parsing it to create HTML.  However, I'm saving the really
tricky Perl Filters for Chris Nandor.<BR>
<H3>Switches</H3>
Finally, a word about switches.  I've seen more than my share of Perl
Filters, and a lot of evidence that MacPerlers in general are unaware of
which #! switches work under MacPerl, and when and how to use them.<BR>This
is really a topic for an entirely separate column, but I'll try to deal
with it briefly here.  Most switches work with MacPerl.  Of those which
might be considered most useful in the context of Perl Filters:<BR>

-n (iterate entire script using <>) works as expected<BR>
-p (iterate entire script using <> printing each line)  <BR>
-l (automatically chomp line endings from input <BR>
   -- with -n or -p no terminating \n needed on output)  <BR>
-e (execute following string as command-line) generates error message -- <BR>
not emulated.  Works only under MPW Perl.<BR>
-0 (sets $\ in octal)  <BR>
<BR>
Jim Correia said in Re: [MacPerl-Scribes] "Basic Perl Filters in BBEdit" <BR>
Colum at Apr/19/2000, Wed 13:30:03.<BR>
<BR>
> Here is quickie example that reverses the selected lines.  If it looks<BR>
> like C it is because I write C all day long and it influences my perl<BR>
> (of which I don't do or know too much):<BR>
> <BR><BR>
> #!perl -w<BR>
> use strict;<BR>
> <BR>
> while ( <> )<BR>
> {<BR>
>     my $s = $_;<BR>
>     <BR>
>     chomp($s);<BR>
>     <BR>
>     my $ct = length($s);<BR>
>     <BR>
>     for(my $i=$ct-1; $i>=0; $i--)<BR>
>     {<BR>
>         print substr($s, $i, 1);<BR>
>     }<BR>
> <BR>
>     print "\n";<BR>
> }<BR>

<BR>  This is a good case study on using #! switches. Perl also does advanced
string handling far better than C (which as I recall doesn't actually *do*
string handling, but I never got anywhere close to understanding C), so a
simple:
<BR><BR>


#!perl -pl
$_ = reverse<BR>
<BR>
does the same thing.  <BR>
<BR>
 I can explain how to get from
Jim's example to mine:
<BR>
First, note that the entire script is encased in a while().  This calls
for
either -p or -n on the hash-bang to remove that construction.<BR>  Second,
note
that the while() ends with a print().  This makes it -p without a doubt.

<BR>Third, note that the script chomp()s input and appends "\n" to its
output.
Assigning  $_ to $s is an uncessary step.  It's more idiomatically perlish
to just "chomp;", which performs chomp($_) by default, thus dropping $s
from the namespace.  This calls for -l, thus removing both chomp() and
print().
<BR>
Since the purpose of the for() loop is duplicated by the built-in function
reverse(), and reverse applies to $_ by default, the entire for loop
becomes "$_ = reverse", and all the associated variables are dropped from
the namespace.  The idiomatic version is **trivially** faster and less
memory intensive.  In practice, both versions are too fast to time.
<BR>

</body>
</html>


---
"the universe is not only queerer than we suppose, but queerer than we can
suppose" -  Haldane
Larry Moore  Fergus On Canada N1M 1V7 ljmoore@freespace.net
http://freespace.net/~ljmoore/Larry_resume.html



==== Want to unsubscribe from this list?
==== Send mail with body "unsubscribe" to macperl-scribes-request@macperl.org