Re: To shell or not to shell (was Re: URL Access Redux)
Re: To shell or not to shell (was Re: URL Access Redux)
- Subject: Re: To shell or not to shell (was Re: URL Access Redux)
- From: Matt Deatherage <email@hidden>
- Date: Tue, 23 May 2006 02:28:02 -0500
On 5/22/06 at 10:21 PM, John C. Welch <email@hidden> wrote:
> Okay, so I'm probably crossing a line, but this is just inane tripe
> and fearmongering. Of course you're seeing more shell here, OS X is
> BASED ON UNIX. To say that you should avoid using shell because this
> is an AppleScript list is like saying you should avoid OSAX because
> they aren't standard. Bulldookey.
This is an effective argument to something other than the question that
Ed raised. It's not all black and white, it's not "use or avoid," it's
not "this is clean, this is dirty." This is, to my mind, the pertinent
section:
On 5/22/06 at 7:55 PM, Stockly, Ed <email@hidden> wrote:
> This list was started because the MacScripter's list became more of a
> Frontier list than anything else and you couldn't ask a simple
> AppleScript question without getting a flood of Usertalk solutions
> that would drown out the AppleScript answers the user was looking for.
>
> The same thing is happening now. It's as if this list has been
> hijacked by shell scripting and the humble AppleScripter is barely
> being supported anymore.
There are things you can't do in AppleScript that you can do by using
Scripting Additions, shell commands, and other scripting languages. The
problem is not that alternate solutions exist, and it's especially not
that shell commands give a way for AppleScripts to perform tasks that
would otherwise be impossible. That's all very good.
What's bad, and what's very bad on this list, is using "external"
methods as the *first* way to get anything done in AppleScript. The
correct answer to "How do I do this in AppleScript" is usually not "do
it in Python," but that's what some people get. I use AppleScript when
I want to work with other applications easily and effectively. When I
do that, I want to keep it all in one script if at all possible. I
don't want to start an Xcode project with an AppleScript file and a Perl
file and a Python file and whatnot.
Last night I was working on a script that required an RFC 822-formatted
date. I quickly figured out AppleScript and standard additions would
not do it for me. I needed this to run on machines with only a small
set of Scripting Additions, and none of those would do it either (though
the next version of one will).
I thought, "well, golly, there has to be a command line tool to do
this," but while I found plenty of programs that did it internally, I
didn't find any that would return an RFC 822 date in the time I had to
do the searching. (One version of "date" does it easily, but the one
installed with Mac OS X apparently does not.)
Now, there are standard Unix C routines to do this, and it would have
been trivial to write a short shell command to do it and invoke it from
AppleScript. But that's *not why I was using AppleScript.* That would
have required a second source file and installing the command on all the
affected machines, where the AppleScript itself just runs inside a
FileMaker script step on any system that can open the database. Writing
the code would have been easier, but managing and deploying it would
have been significantly harder.
(This is not anyone's cue to tell me how easy this-or-that project
management is, or how to set variables to find commands local to a
filemaker directory, etc. I consider those techniques just as fragile
as installing a second code file to make a script work. If those
techniques work for you, more power to you.)
I eventually wound up rolling my own in AppleScript (blank lines between every code line, since I don't want to try to reformat it for Email):
---
on RFC822Date(ourDate)
set ourWeekday to characters 1 thru 3 of ((weekday of ourDate) as string) as string
set ourDay to day of ourDate
set ourMonth to characters 1 thru 3 of ((month of ourDate) as string) as string
set ourYear to year of ourDate
set ourHours to (characters -2 thru -1 of ("00" & hours of ourDate)) as string
set ourMinutes to (characters -2 thru -1 of ("00" & minutes of ourDate)) as string
set ourSeconds to (characters -2 thru -1 of ("00" & seconds of ourDate)) as string
set GMTshift to ((time to GMT) div 3600)
set GMTremainder to ((time to GMT) mod 3600)
if GMTshift ≤ 0 then
set ourOffset to "-" & (characters -2 thru -1 of ("00" & (GMTshift * -1)) as string) & (characters -2 thru -1 of ("00" & (GMTremainder * -1)) as string)
-- yes, remainders of negative numbers are also negative
else
set ourOffset to "+" & (characters -2 thru -1 of ("00" & GMTshift) as string) & (characters -2 thru -1 of ("00" & GMTremainder) as string)
end if
set ourResult to ourWeekday & ", " & ourDay & " " & ourMonth & " " & ourYear
set ourResult to ourResult & " " & ourHours & ":" & ourMinutes & ":" & ourSeconds & " " & ourOffset
return ourResult
end RFC822Date
---
Horribly inefficient? Could be optimized? Could be shorter? Sure, but
it took almost no time to write, it's fast enough for my use, and it
eliminates dependencies on external files. *I did it in AppleScript.*
The same script, as it turns out, *has* to use "do shell script" to use
an open-source command that will only function on one piece of data at a
time, so I wind up invoking it hundreds of times. Because of that, the
script takes a very long time to run (about 30 seconds when, without the
shell part, it would take about 3 seconds). The shell command itself is
not slow, but executing it over and over is. I'll try to figure out a
way to call it hundreds of times from one "do shell script" line,
probably by writing a temp file and executing that.
I *had* to use the shell for that, and I was perfectly willing to use
the shell for a quick RFC 822 date, but not when it got to the point of
writing a completely separate shell program. Going outside the
AppleScript language should be a *last* resort on an AppleScripting
list, not the first answer. There are plenty of times when the answer
is "You can't do that in AppleScript, so here are some suggestions."
There are also plenty of times when you could easily do something in
AppleScript without spawning shells or writing separate scripts in other
languages. All Ed asked was that external programs not be the first,
default answer to AppleScript questions.
I wouldn't want anyone to censor their answers because something
required a shell script, if that's the only way they know how to do it.
The same thing came up today on the Quartz list in different form: a C
programmer wanted to set a custom cursor, and the answer was "You can't
right now: the only way is to call NSCursor, and that requires Objective
C." He didn't want to hear it, but it was still true. There are times
when the single factual answer on this list is "You can't do it in
AppleScript. Here are some ideas for using other languages from within
AppleScript."
I would be quite pleased, however, if the implicit tone of "AppleScript
is weak and broken, use *real* Unix languages instead" in several
answers went away. The Quartz answer about NSCursor did not imply that
the programmer should move away from C++ and Carbon and use Cocoa, a
"real" Mac OS X framework, instead. It just admitted that Objective-C
was his only route to accomplish his task, and said he could roll it in
with little fuss. So it is with 'do shell script' and AppleScript, but
often, the tone seems to be that even *trying* to write things in
AppleScript is a bad idea.
This list shouldn't be a point of evangelism for people who want others
to use languages other than AppleScript. I'm not encouraging anyone to pretend that AppleScript doesn't have flaws. I'm encouraging people not to punt on first down.
--Matt (yes, it was long, but I provided code to make up for it)
--
Matt Deatherage <email@hidden>
GCSF, Incorporated <http://www.macjournals.com>
Some days you're the pigeon, and some days you're the statue.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Applescript-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden