|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171
|
|
Chapter 12:
|
|
|
|
The MacPerl Package
|
|
"Several large, artificial constructions are approaching us,"
ZORAC announced after a short pause.
"The designs are not familiar,
but they are obviously the products of intelligence.
Implications: we have been intercepted deliberately
by a means unknown, for a purpose unknown,
and transferred to a place unknown by a form of intelligence unknown.
Apart from the unknowns, everything is obvious."
|
|
- James P. Hogan, Giants Star
|
|
Because MacPerl runs on Mac OS, it has some different requirements than do
Perl versions for other platforms. Some of the differences have to do with
the filesystem, others with processes, inter-application communication, or
built-in OS scripting. Because of these differences, special functionality
has been included in MacPerl that is not found on other platforms.
|
|
Matthias Neeracher, the author of MacPerl, has written many MacPerl-
specific modules and functions for the MacPerl distribution. These functions
vary in complexity and utility, but they all have one main purpose: to
make your Mac OS scripting easier and more powerful.
|
|
Note:The first time we introduce a function, we will list its expected
arguments using single, fully capitalized words, with square brackets
enclosing optional arguments, as: FooBar(ABC [, DEF]), where
function FooBar()takes the required parameter ABCand the optional
parameter DEF.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MacPerl's built-in functions and variables are accessible just like any Perl
function or special variable, with one caveat: they must be accessed via the
MacPerlpackage.1,2So, you must use the packageMacPerldirective
before referencing these items or access them (from outside that package)
with the double-colon syntax.3
|
|
Volumes, Paths, And File Specifications
|
|
Probably the most noticeable difference between MacPerl and other forms of
Perl is in the specification of pathnames(see the previous chapter). Mac
OS syntax uses colons, rather than (back-)slashes, to separate the elements
of the name. Also, there is no overall "root" for the file tree as a whole.
|
|
Complicating the situation still further, Mac OS programs are able to use
an alternate form of specifying a file: the file system specification record
(filespec). A filespec is a special encoding of the path name which is guar-
anteed to be unique for every file. These lines could specify the same file:
|
|
$path = 'HD:MacPerl :Shuck Manual';
$fss= ' FFFF000114B7:Shuck Manual';
|
|
As used by MacPerl, a filespec starts with a character (possibly invisible,
depending on your font) whose high (i.e., sign) bit is set. It continues with a
series of letters and numbers, followed by a colon and a filename.
|
|
Note:The "series of letters and numbers" encodes a unique identifier for
the hard disk partition and folder that contain the file. Unlike a path
name, the identifier will continue to "point to" the folder as long as the
folder exists (even if the folder is moved a different location).
|
|
If the file is removed and replaced by a file with the same name, the
identifier will also continue to work. If the folder is removed, how-
|
|
|
|
1MacPerl also includes modules which are useful for dealing with the Mac OS
Toolbox. We will introduce these modules in the next chapter.
|
|
2Actually, we lied. They can also be exported into the current package by the
MacPerlmodule if asked for explicitly:
use MacPerl qw(Ask Answer Pick); $x = Answer('Hello');
|
|
3Interesting note: a package's symbol table is a hash. To see every symbol available in
a given package, try:
foreach (keys(%MacPerl::)) {print "$_ => $MacPerl::{$_}\n"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ever, the identifer will not "find" a new folder with the same name. In
short, the semantics of filespecs is notthe same as that of path names.
|
|
In many situations, either a path name or a filespec can be used; open(),
for instance, will accept either one. In some cases, however, a function may
require a filespec instead of a path. Also, some functions returnfilespecs; if
your program isn't ready for a filespec, it won't know what to do with it.
|
|
Luckily, the MacPerlpackage provides these translation functions:
|
|
MakeFSSpec(PATH)# convert path to filespec
MakePath(FSSPEC)# convert filespec to path
|
|
Volumes()is a good way to practice with filespecs and paths. In a scalar
context, this function returns the filespec of the startup volume. In a list con-
text, it returns the filespecs of all available volumes, in the order that
they were mounted (the startup volume is always first). The script below
uses Volumes()to display these filespecs, sorted by volume name:
|
|
$svol = MacPerl::Volumes();
print "The path name of the startup volume is:\n";
printf("%s\n", MacPerl::MakePath($svol));
|
|
print "The filespecs of the other volumes are:\n";
@vols = MacPerl::Volumes();
foreach $vol (sort(@vols)) {
printf("%s\n", MacPerl::MakeFSSpec($vol))
if ($vol ne $svol);
}
|
|
Note that we called MakeFSSpec()on the volumes, even though they
already are filespecs. This works because MakeFSSpec()and MakePath()
return the right thing whether they receive a filespec or a path. If you
aren't sure which one you have in your variable, feel free to pass it through
either function to ensure that you will get what you need.
|
|
File Information
|
|
Each Mac OS files has a creatorand a type. A document's creator (applica-
tion ID) is the same as that of its assigned application. The type encodes
the type of document (e.g., text or graphic file).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For instance, script files that "belong" to MacPerl have the creator McPL
and the type TEXT.4Files created by MacPerl's open()function have, by
default, the creator 'MPS '(MPW's application ID) and type TEXT.5
|
|
SetFileInfo(CREATOR, TYPE, FILES)applies the specified creator
and type to a list of files. GetFileInfo(FILE)returns either the file type
(in a scalar context) or an array of the creator and type (in a list context).
|
|
This short script opens a directory and looks through all of the files. If a
file is of type TEXT, the script changes the file's creator to R*ch(BBEdit's
application ID).
|
|
#!perl -w
my($dir, $file, @files);
$dir = 'HD:Desktop Folder:Text Files';
|
|
chdir($dir);
opendir(D, $dir) or die($!);
|
|
foreach $file (readdir(D)) {
if (-f $file &&
MacPerl::GetFileInfo($file) eq 'TEXT') {
push(@files, $file);
}
}
MacPerl::SetFileInfo('R*ch', 'TEXT', @files);
|
|
Answer, Ask, Pick
|
|
These three basic dialog functions are extremely useful for putting a quick
Graphical User Interface(GUI) on top of an otherwise text-based script.
They are normally the best way to get simple user input.6
|
|
Answer(PROMPT [, BUTTON1, BUTTON2, BUTTON3])puts up a dialog
box with a message (PROMPT) and a choice of buttons for the user to click.
|
|
|
|
4MacPerl itself has type APPL (as all applications do) and, of course, creator McPL.
For more about creator IDs, see Chapter 13, The Toolbox Modules.
|
|
5If you know how to use ResEdit, you can change the default in MacPerl's
GU I
resource ID 12040. Do not attempt this if you do not know what you are doing.
|
|
6There are also several GUI modules for more advanced interaction; these are
discussed in Chapter 14, GUI Toolbox Modules.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If BUTTON1is unspecified, it will be given the label OK. Thus, the calls
Answer('Wake Up')and Answer('Wake Up', 'OK')do exactly the
same thing. Both return a dialog box that says Wake Upand has a single,
highlighted button that reads OK.
|
|
The buttons are displayed in reverse order. The first button passed to the
function - which is the last button displayed on the screen - is always
highlighted. So, the following call will print a dialog box with three
buttons - Yes, No, and Maybe, in that order - with Maybehighlighted:
|
|
$ans = MacPerl::Answer('Are you awake?',
'Maybe', 'No', 'Yes');
|
|
|
|
Then, of course, you want to get a value back to find out what the user has
clicked. The first button on the screenalways returns a 0. Since the last but-
ton passed to the variable is always first in the dialog box, clicking on OKin
the following examples always returns 0:
|
|
$an1 = MacPerl::Answer('Delete?', 'Huh?', 'No', 'OK');
$an2 = MacPerl::Answer('Delete?', 'No', 'OK');
$an3 = MacPerl::Answer('Delete?', 'OK');
$an4 = MacPerl::Answer('Delete?');
|
|
Ask(PROMPT [, DEFAULT])is similar, but instead of having buttons to
return a value, it has a text input box. Like Answer(), the first argument is
the prompt. The second argument, which is optional, allows you to put some
default text into the box for the user.
|
|
The value returned by the function is the text that is in the box when the
user clicks OK. If the user clicks Cancel, the function returns undef.
|
|
Note:User-supplied data should always be considered tainted, and is
usually tainted under Unix Perl. However, the special MacPerl routines
generally do not taint this data. You might want to consider using the
Taint module from the CPAN, with which you can intentionally taint
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
any data you have. See Chapter 16, CGI Scripting, and perlsecfor
more details on tainting.
|
|
$name= MacPerl::Ask('What is your name?');
$quest = MacPerl::Ask('What is your Quest?',
'I seek the Holy Grail');
|
|
|
|
Pick(PROMPT, VALUES)allows you to put up a scrolling list of items.
Again, the first argument is the text prompt for the dialog box. But here,
the number of following arguments is limited only by memory, and each
argument will be a value in the list. Again, the selected value will be
returned if the user clicks OK, and undefwill be returned on Cancel.
|
|
$suit = MacPerl::Pick('Pick a Suit',
qw(Hearts Spades Diamonds Clubs));
$card = MacPerl::Pick('Pick a Card',
('A', 2..10, 'J', 'Q', 'K'));
|
|
|
|
You can also have MacPerl::Pickallow the picking of multiple items by
assigning it in a list context, as in:
|
|
@major = MacPerl::Pick('Your college major(s)',
qw(Psychology Sociology Journalism));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Quit
|
|
Quit(LEVEL)sets a flag that tells MacPerl whether or not to quit after
the current script has finished execution. It does not quit until the script is
finished, if at all. LEVELdefines under what conditions this happens, as:
|
|
0
1
2
3
|
Do not quit.
Only quit if this is a "runtime" script.
Always quit.
Only quit if this is the first script run since MacPerl was launched.
|
|
MacPerl::Quit(2);
MacPerl::Quit(0) if MacPerl::Answer(
'Should I stay or should I go?', 'Stay', 'Go'
);
|
|
$Version
|
|
$Versionis the one item in the MacPerlpackage that is not a function. It
is a read-only scalar variable that holds the MacPerl version information.
This differs from the special Perl variable $], which holds the version of
the Perl sources from which MacPerl is built.
|
|
$Versionalways changes when a new MacPerl is released, but often those
releases are based on the same Perl sources, so $]doesn't always change.
|
|
print "MacPerl $MacPerl::Version, Perl version $]";
|
|
Displays a line of the form:
|
|
MacPerl 5.1.9r4 Application, Perl version 5.004
|
|
LoadExternals
|
|
One really nifty feature of MacPerl is its ability to use other Mac OS lan-
guages. LoadExternals()is a way to use XFCN and XCMD extensions,
which are commonly used in HyperCard scripting. The argument passed is a
library file, with the same path rules as require.
|
|
Dartmouth College has developed some useful XFCNs and XCMDs. One of
them, for Clipboard access, is on our CD-ROM. Copy Clipboard.XFCNto your
site_perlfolder. This file contains an XFCN that can copy information to
and from the Mac OS clipboard, by means of the Clipboard()function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If an argument is passed, LoadExternalsputs it on the Mac OS clipboard.
Otherwise, it returns the contents of the Clipboard. Note that, because
LoadExternals()brings functions directly into the current package, many
people prefer to call the function from a separate package.
|
|
package Dartmouth;
MacPerl::LoadExternals("Clipboard.XFCN");
|
|
package main;
Dartmouth::Clipboard("D'oh!");
print Dartmouth::Clipboard(), "\n";
|
|
If everything has worked properly, the specified text should land on the
Clipboard (D'oh!). You can go to the Finder and select Show Clipboardfrom
the Editmenu to prove it to yourself, if you like, or just paste it somewhere.
|
|
DoAppleScript
|
|
DoAppleScript(SCRIPT)takes the text of an AppleScript as its argu-
ment. We'll cover this more in Chapter 18, AppleScript, Etc.
|
|
$script = <<EOS;
tell application "MacPerl"
make new window
copy "MacPerl: Power and Ease" to character 1 of front
window
end tell
EOS
MacPerl::DoAppleScript($script);
|
|
Reply
|
|
Reply(REPLY)is used primarily for returning data to programs that call
MacPerl. For example, AppleScript can call MacPerl as follows:7
|
|
tell application "MacPerl"
Do Script "MacPerl::Reply('Hello')"
end tell
|
|
If run from Script Editor, Apple's AppleScript editor, this will return the
text "Hello". We will see more of this in Chapter 18, AppleScript, Etc.
|
|
|
|
7Remember, this is AppleScript code and will not run as-is in MacPerl.
|
Copyright © 1997-1998 by Prime Time Freeware. All Rights Reserved.