ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> pythoncard
pythoncard
[Pythoncard-users] scriptlets
by Kevin Altis other posts by this author
Apr 23 2002 8:56PM messages near this date
[Pythoncard-users] OS X Success | [Pythoncard-users] showing and moving the main window
Applications often have macro languages or their own proprietary scripting
languages for automating tasks and extending the functionality of the
application. One of the advantages of using Python as the language to build
applications is that it can also be used as the built-in scripting language
for an application. We have a built-in shell in PythonCard that can execute
one statement at a time or an entire file at once using the shell runfile()
method. What if we used the shell to run add-on scripts in an app at
runtime?

Dan Shafer and I came up with the idea of calling these Python scripts that
you run from within an application, "scriptlets". Scriptlets are used sort
of like macros in other apps. The scripts aren't standalone because they are
meant to access the components and methods of an app. They generally aren't
very long or complex, but they can be. If you wanted to define new classes,
methods, functions, etc. in a scriptlet that is certainly possible. A
scriptlet is "played back" in the shell when you execute it. Essentially
running a scriptlet is no different than if you typed those lines in the
shell yourself, so you can type something in the shell and test a groups of
commands before saving it as a scriptlet.

So, what's the point of a scriptlet compared to adding code to your main
app. Users can write or use scriptlets they get from other people without
ever modifying the main source of an application. So, scriptlets end up
acting as a way of extending the functionality of an application. By using
scriptlets, you can also avoid feature bloat. If a feature is used
frequently, it should probably be a standard part of the app UI, but
otherwise it should probably just be an extension. Scriptlets are Python
scripts, so you can edit them using the same editor you use for other Python
source code.

To experiment with this idea I've made an addition to the textEditor sample.
It now has a Scriptlet menu. You can hide/show the shell window, save a
selection in the shell as a scriptlet and run a scriptlet. I also added a
'scriptlets' sub-directory which contains a number of example scripts.

Here's the insertDateAndTime.py scriptlet

import time
now = time.localtime(time.time())
dateStr = time.strftime("%A, %B %d, %Y,  %I:%M %p", now)
comp.fldDocument.replaceSelection(dateStr)

Pretty simple, but this can be a handy addition if you use the textEditor
sample and it is easy for a user to change the format string used to build
the date/time. 'comp' (self.components inside a method of the main app or
bg.components in the shell) is assumed to be already defined in the shell
namespace. Some other scriptlets are checked into cvs here:

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/pythoncard/PythonCardPrototyp
e/samples/textEditor/scriptlets/

Feel free to come up with your own scriptlet examples either for the
textEditor sample or some other samples and share them on the list. We can
modify other samples as necessary while we explore this scriptlet concept.
One possible use of scriptlets is for testing. If you have been executing a
series of steps over and over again in the shell as you build and test your
app, that might be a good candidate for a scriptlet that you can run on
demand. A scriptlet can access any part of an app, display dialogs and get
user input, whatever you want.

After we experiment with this Scriptlet idea and if it seems to work for
everyone, then we could make a Scriptlet menu a standard part of the
framework and any app could get one for free, simply by checking an option
for the Scriptlet menu in the resourceEditor, just like you do for a
statusbar. Another feature which I would like to have, but which I can't
really do until I refactor the menu.py module is to be able to dynamically
add and remove specific scriptlets to the Scriptlet menu, maybe even with
key bindings. This would allow the user to skip the step of locating the
scriptlet via a dialog for repeat invocations.

This may be a difficult concept to grasp either because I've done a poor job
of explaining it or that it is just plain difficult to see the
possibilities, so don't hesitate to ask "dumb questions" on the list so we
can explore this as a group more effectively.

In HyperCard, there was a message box that was sort of like our Shell,
except that the message box only had a single line, so you couldn't type in
a whole function or multiline script and execute that dynamically. If you
are used to HyperCard, it might help to think of the Shell as a much more
powerful message box. Visual Basic has something called the Immediate Window
used for debugging. Again, our Shell is much more powerful than the VB
Immediate window, but when you start thinking about and using the shell it
might help thinking about it as an "Immediate Window".


Some technical details:
I modified how the framework starts up so that the shell is always loaded,
but it isn't visible by default unless you pass the -s command-line. Thus,
all the samples should run just as they have been.

The shell's runfile method is already used to execute the pycrustrc.py files
when a PythonCard app starts up. The pycrustrc.py file is basically a
scriptlet. The implementation of Scriptlets that I've done uses the shell
for executing a script to guarantee a uniform namespace when executing a
scriptlet and so that scriptlets can be "chained" together with each
scriptlet you run modifying the shell namespace.

The built-in execfile() function in Python can also be used to execute a
files contents with an optional global and local namespace. There are
additional ways to run files in Python, but for our purposes the central
issue is probably the namespace that the script is executed in and
leveraging the shell rather than having multiple ways of doing essentially
the same thing.

If we execute a file in the shell, then there is a record of each command as
it executes. The shell can also be used for minor editing, copying a group
of commands and then saving those commands to a file. If a series of
commands are executed in the shell then the results of those commands will
impact the shell namespace. I don't think that is true for execfile.

The biggest problem right now with executing scriptlets in the shell, is
that Patrick probably needs to refactor the runfile() method to better
handle scripts that don't have blank lines between blocks of code and other
spacing issues.

If you experiment with scriptlets, you may want to rename textEditor.pyw to
textEditor.py or make a copy of textEditor.pyw and rename it to
textEditor.py so that you'll have a console to display error messages. You
can also use the shell method, redirectStdout() to cause sys.stdout output
to be redirected to the shell.

> >> shell.redirectStdout(1)

ka


_______________________________________________
Pythoncard-users mailing list
Pythoncard-users@[...].net
https://lists.sourceforge.net/lists/listinfo/pythoncard-users

Privacy Policy | Email Opt-out | Feedback | Syndication
© 2004 ActiveState, a division of Sophos All rights reserved