Smalltalk Development on XO: Difference between revisions
No edit summary |
(→Submit your changes: adjust URLs to reflect current locations) |
||
(17 intermediate revisions by 12 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Programming_language]] |
|||
== General Introduction == |
== General Introduction == |
||
The [[Etoys]] activity installed on XO is written in the [[Squeak]] |
The [[Etoys]] activity installed on XO is written in the [[Squeak]] |
||
⚫ | |||
system. Namely, it comes with all development tools and class |
|||
end-users, but it is just a kids' playground guarded by soft fences, |
|||
⚫ | |||
so to speak. Once you make a hole on the fences and get outside, you |
|||
⚫ | |||
Once you make a hole on the fences and get outside, you will have |
|||
⚫ | |||
⚫ | |||
that all files that the core developers of the activity uses are |
|||
⚫ | |||
shipped with XO; this means that even if the only computer you have is the XO, |
|||
⚫ | |||
you can develop as much as any of the core developers do with Etoys, |
|||
and if you prove that you are good, you can be a core developer of the |
|||
default activity on XO. Sounds exciting? |
|||
On this page, I'll explain how to disable the fences, write code, save |
|||
⚫ | |||
== Set up Your Files == |
== Set up Your Files == |
||
First, you copy two files from /usr/share/etoys to a location where |
First, you copy two files from '''/usr/share/etoys''' to a location where |
||
the user "olpc" can write. Follow the steps described below: |
the user "olpc" can write. Follow the steps described below: |
||
Do either one of following |
Do either one of following two options (2.1 "Copy Files to /media" or |
||
2.2 "Use USB memory"). If you don't have a USB memory handy or you |
|||
would like to do it without one, do 2.1. Otherwise, do 2.2. |
|||
don't mind changing a system file and know how to edit a text file, do |
|||
2.2. You're fortunate to have an external USB flash memory, do 2.3. |
|||
=== Copy Files to /media === |
=== Copy Files to /media === |
||
Open the "Console" activity. and execute following commands: |
Open the "Console" activity. and execute the following commands: |
||
% su |
% su |
||
# mkdir -p /media/foo/olpc-dev |
# mkdir -p /media/foo/olpc-dev |
||
# chown olpc:olpc /media/foo/olpc-dev |
# chown olpc:olpc /media/foo/olpc-dev |
||
# chmod 777 /media/foo/olpc-dev |
|||
# cd /usr/lib/squeak/3* |
# cd /usr/lib/squeak/3* |
||
# ln -s ../../../share/etoys/ |
# ln -s ../../../share/etoys/EtoysV3.sources |
||
# exit |
# exit |
||
% cp /usr/share/etoys/etoys.{image,changes} /media/foo/olpc-dev |
% cp /usr/share/etoys/etoys.{image,changes} /media/foo/olpc-dev |
||
% chmod 666 /media/foo/olpc-dev/etoys* |
% chmod 666 /media/foo/olpc-dev/etoys* |
||
<!-- |
|||
=== Edit /usr/bin/etoys === |
=== Edit /usr/bin/etoys === |
||
* Edit /usr/bin/etoys shell script so that the ALTIMG variable definition in it reads: |
* Edit '''/usr/bin/etoys''' shell script so that the ALTIMG variable definition in it reads: |
||
ALTIMG=/home/olpc/etoys.image |
ALTIMG=/home/olpc/etoys.image |
||
Then, execute following commands in the "Console" activity. |
Then, execute the following commands in the "Console" activity. |
||
# su |
# su |
||
# cd /usr/lib/squeak/3* |
# cd /usr/lib/squeak/3* |
||
# ln -s ../../../share/etoys/ |
# ln -s ../../../share/etoys/EtoysV3.sources |
||
# exit |
# exit |
||
% cp /usr/share/etoys/etoys.{image,changes} /home/olpc |
% cp /usr/share/etoys/etoys.{image,changes} /home/olpc |
||
% chmod 666 /home/olpc/etoys.* |
% chmod 666 /home/olpc/etoys.* |
||
--> |
|||
⚫ | |||
⚫ | |||
* Plug your USB memory into a slot, start the "Console" activity and execute the following: |
* Plug your USB memory into a slot, start the "Console" activity and execute the following: |
||
% cd /media/* |
% cd /media/* |
||
% mkdir olpc-dev |
% mkdir olpc-dev |
||
% cp /usr/share/etoys/etoys.{image,changes} olpc-dev |
% cp /usr/share/etoys/etoys.{image,changes} olpc-dev |
||
% ln -s /usr/share/etoys/ |
% ln -s /usr/share/etoys/EtoysV3.sources olpc-dev |
||
% chmod 666 olpc-dev/etoys.* |
% chmod 666 olpc-dev/etoys.* |
||
(In the first |
(In the first option, you could make the symbolic link to /usr/share/etoys/EtoysV3.sources from the location where your etoys.image will reside. In a future version, we would include the symbolic link from /usr/lib/squeak/3.9-12 or such automatically.) |
||
Note that your USB memory must be formatted with a filesystem that can support symbolic links, such as <i>ext2</i> or <i>ext3</i>. |
|||
Also, the mountpoint must be writable by user "olpc", |
|||
or else the [[Journal]] activity will not recognize the external storage. |
|||
([[Journal]] will attempt to create a directory '''.olpc.store''' in the root of the storage device to host its metadata. |
|||
Once this is created with the proper permissions, perhaps the mountpoint could revert to ownership by root.) If your USB memory is not formatted to support symbolic links and there is enough space on the USB memory device, you can just copy the EtoysV3.sources file instead of making a symbolic link. |
|||
As you might see, the purpose of this step is to make a copy of |
As you might see, the purpose of this step is to make a copy of |
||
etoys.image and etoys.changes and put them |
etoys.image and etoys.changes and put them under |
||
/media/<i>vol-name</i>/olpc-dev, make the directory writable, and put |
|||
/usr/bin/etoys shell script searches for the alternative .image file. |
|||
writable copies of etoys.image and etoys.changes in the directory. |
|||
/usr/bin/etoys first looks for the alternative .image file, and when |
|||
it cannot find it, it uses the default .image file placed at |
|||
If you can read a shell script, take a look at /usr/bin/etoys. The |
|||
/usr/share/etoys. The idea here is to create alternative .image and |
|||
ALTIMG variable specifies where to look for alternate .image. You |
|||
companion .changes file that are writable. .image and .changes should |
|||
could edit the shell script and specify your own .image file anywhere |
|||
always go together. If you would like to rename the base name of |
|||
in the file system. |
|||
them, use the same base name for both of them, and keep them in the |
|||
same directory. |
|||
== Start Up Etoys and Change Preferences == |
== Start Up Etoys and Change Preferences == |
||
Now, bring up the Sugar frame (either going to the donut view or press |
Now, bring up the Sugar frame (either going to the donut view or press |
||
the frame button), and click on the shooting star to launch Etoys. |
the frame button), and click on the shooting star to launch Etoys. |
||
Since the .image is exact copy of the default one so far, you might |
Since the .image is an exact copy of the default one so far, you might |
||
not see whether your image is launched or not. First, |
not see whether your image is launched or not. First, you need to |
||
know how to break in the fences put around Etoys. What we would like |
know how to break in the fences put around Etoys. What we would like |
||
to do is to turn off "eToyFriendly" preference and set up a few other |
to do is to turn off "eToyFriendly" preference and set up a few other |
||
Line 75: | Line 91: | ||
[[Image:worldMenu.png|right|thumb|The World Menu]] |
[[Image:worldMenu.png|right|thumb|The World Menu]] |
||
# Press, Alt-, (i.e., hold the Alt key first, and while you are holding it, hit "," key and then release Alt key) or (if we fix a bug) do the "show source" gesture. You'll get a menu that |
# Press, Alt-, (i.e., hold the Alt key first, and while you are holding it, hit "," key and then release Alt key) or (if we fix a bug) do the "show source" gesture. You'll get a menu that looks like Figure "Show Source". |
||
# From the menu, choose 'help...' and 'preferences...'. Depending on the language setting, these menu items may be translated. But you should be able to figure them out. You get a Preference Panel that looks like Figure "Preferences Panel".# In the Preference Panel, click on the button labeled "scripting", and uncheck "eToyFriendly" box. This may take 10 seconds or so; be patient. |
# From the menu, choose 'help...' and 'preferences...'. Depending on the language setting, these menu items may be translated. But you should be able to figure them out. You get a Preference Panel that looks like Figure "Preferences Panel".# In the Preference Panel, click on the button labeled "scripting", and uncheck "eToyFriendly" box. This may take 10 seconds or so; be patient. |
||
# After it is done, now you can bring up the vital "World menu" by just |
# After it is done, now you can bring up the vital "World menu" by just clicking on the empty area of screen. The World menu looks like Figure "The World Menu". |
||
# Now, try to choose "save" (fifth from the bottom). If the .image you are on is indeed the writable one, it will update the .image and .changes files on the disk. If you do not see a pink small dialog pops up but the cursor changes a pen-shape momentarily, the files are successfully saved. If you see a pink dialog, go back to the previous section and make sure you are doing it right. (If you know how to get a Workspace, try to evaluate expressions like "Smalltalk imagePath".) |
# Now, try to choose "save" (fifth from the bottom). If the .image you are on is indeed the writable one, it will update the .image and .changes files on the disk. If you do not see a pink small dialog pops up but the cursor changes to a pen-shape momentarily, the files are successfully saved. If you see a pink dialog, go back to the previous section and make sure you are doing it right. (If you know how to get a Workspace, try to evaluate expressions like "Smalltalk imagePath".) |
||
# For what we are going to do (write your own code), having a car running around in front of you may be disturbing (either a virtual car or real car). Get the World menu again, and choose "previous project" at the top. You'll be taken to an empty project, which is more suitable to do the following and more. Save your image again after that. |
# For what we are going to do (write your own code), having a car running around in front of you may be disturbing (either a virtual car or real car). Get the World menu again, and choose "previous project" at the top. You'll be taken to an empty project, which is more suitable to do the following and more. Save your image again after that. |
||
Line 87: | Line 103: | ||
intercepts some of the Alt-key combinations so this can be very |
intercepts some of the Alt-key combinations so this can be very |
||
dangerous. For example, when you press Alt-c to mean to copy text, |
dangerous. For example, when you press Alt-c to mean to copy text, |
||
Sugar interprets it as quit and |
Sugar interprets it as quit and kills your Squeak session. Another |
||
preference is "swapMouseButtons" preference. During development, you |
preference is "swapMouseButtons" preference. During development, you |
||
would rather use the right mouse button to bring up context menus |
would rather use the right mouse button to bring up context menus |
||
Line 107: | Line 123: | ||
To resume a previously-saved session, click on the shooting star icon |
To resume a previously-saved session, click on the shooting star icon |
||
in the Sugar frame. The exact environment you saved will be resumed. |
in the Sugar frame. The exact environment you saved will be resumed. |
||
(But there is a bug that takes you to the Launcher project. |
(But there is a bug that takes you to the Launcher project. A later |
||
version of standard image doesn't do it if eToyFriendly is off.) Yes, |
version of standard image doesn't do it if eToyFriendly is off.) Yes, |
||
Sugar's idea of continuous running activities you only suspend and |
Sugar's idea of continuous running activities you only suspend and |
||
resume have a root in this Smalltalk's idea. However, beware a |
resume have a root in this Smalltalk's idea. However, beware of a |
||
difference; Squeak does not save its image automatically upon exit. |
difference; Squeak does not save its image automatically upon exit. |
||
You even have an option to say "quit", to mean "quit without save". |
You even have an option to say "quit", to mean "quit without save". |
||
You can also copy your .image and .changes pair to a non-XO |
You can also copy your .image and .changes pair to a non-XO |
||
environment (Windows, Mac, Linux or |
environment (Windows, Mac, Linux or two dozen of other different |
||
kinds of platforms) and resume the session on it. The screen extent |
kinds of platforms) and resume the session on it. The screen extent |
||
may be different on a different computer but otherwise the exact |
may be different on a different computer but otherwise the exact |
||
Line 125: | Line 141: | ||
% squeak your-favorite.image |
% squeak your-favorite.image |
||
(There are some command line options you might want |
(There are some command line options you might want to provide. |
||
see /usr/bin/etoys if you want to follow what it does.) |
see /usr/bin/etoys if you want to follow what it does.) |
||
Line 133: | Line 149: | ||
== Basic Programming Tools == |
== Basic Programming Tools == |
||
Describing full |
Describing the full details of Smalltalk development techniques is not the |
||
scope of this page, but I describe some basics. |
scope of this page, but I will describe some basics. |
||
From the 'open...' menu in the World menu, you can access the most |
From the 'open...' menu in the World menu, you can access the most |
||
Line 140: | Line 156: | ||
one, resize it to a fairly small size (a height enough for 5 lines or |
one, resize it to a fairly small size (a height enough for 5 lines or |
||
such is usually ok). Equally handy is a Workspace. Get one from |
such is usually ok). Equally handy is a Workspace. Get one from |
||
'workspace (k)' menu item. In there type "3 + 4", put the text |
'workspace (k)' menu item. In there, type "3 + 4", put the text |
||
insertion cursor on the line, get the context menu (by right-clicking |
insertion cursor on the line, get the context menu (by right-clicking |
||
on the pane, or if swapMouseButtons is not set, click on a square |
on the pane, or if swapMouseButtons is not set, click on a square |
||
button above the vertical scroll bar), and choose "print it (p)". It |
button above the vertical scroll bar), and choose "print it (p)". It |
||
executes the expression and |
executes the expression and prints the result. (See Figure "Workspace and Transcript".) |
||
[[Image:workspaceAndTranscript.png|right|thumb|Workspace and Transcript]] |
[[Image:workspaceAndTranscript.png|right|thumb|Workspace and Transcript]] |
||
The main programming tool in Squeak is "System Browser", which is |
The main programming tool in Squeak is "System Browser", which is |
||
available from 'browser (b)' menu item in 'open...'. (You rarely need |
available from 'browser (b)' menu item in 'open...'. (You rarely need |
||
to instantiate a Browser from menu. Because you have one or any other |
to instantiate a Browser from the menu. Because you have one or any other |
||
text pane opened, you can instantiate more from it with keyboard short |
text pane opened, you can instantiate more from it with keyboard short |
||
cuts.) (See Figure "System Browser".) |
cuts.) (See Figure "System Browser".) |
||
Line 160: | Line 176: | ||
[[Image:findClass.png|right|thumb|Find a class]] |
[[Image:findClass.png|right|thumb|Find a class]] |
||
You might want to resize the Browser. In the second from bottom pane, |
You might want to resize the Browser. In the second from bottom pane, |
||
you see |
you see text that looks like: |
||
BorderedMorph subclass: #RectangleMorph |
BorderedMorph subclass: #RectangleMorph |
||
instanceVariableNames: '' |
|||
classVariableNames: '' |
|||
poolDictionaries: '' |
|||
category: 'Morphic-Basic' |
|||
Replace it with |
Replace it with |
||
RectangleMorph subclass: #MyMorph |
RectangleMorph subclass: #MyMorph |
||
instanceVariableNames: '' |
|||
classVariableNames: '' |
|||
poolDictionaries: '' |
|||
category: 'Morphic-Basic' |
|||
Get the context menu in the pane and choose "accept (s)". (See Figure |
Get the context menu in the pane and choose "accept (s)". (See Figure |
||
Line 224: | Line 240: | ||
lines and execute them like a method. |
lines and execute them like a method. |
||
Similar |
Similar things can be done from an "inspector". Alt-click on the |
||
instance of MyMorph on screen to get halo. With "eToyFriendly" |
instance of MyMorph on screen to get halo. With "eToyFriendly" |
||
preference off, you have an extra handle looks like a wrench (See |
preference off, you have an extra handle that looks like a wrench (See |
||
Figure "Debug Handle".) |
Figure "Debug Handle".) |
||
[[Image:debugHandle.png|right|thumb|Debug Handle]] |
[[Image:debugHandle.png|right|thumb|Debug Handle]] |
||
Line 245: | Line 261: | ||
RectangleMorph subclass: #MyMorph |
RectangleMorph subclass: #MyMorph |
||
instanceVariableNames: '' |
|||
classVariableNames: '' |
|||
poolDictionaries: '' |
|||
category: 'Morphic-Basic' |
|||
Put the text selection cursor in between the single quotes after |
Put the text selection cursor in between the single quotes after |
||
Line 255: | Line 271: | ||
RectangleMorph subclass: #MyMorph |
RectangleMorph subclass: #MyMorph |
||
instanceVariableNames: 'timeLimit' |
|||
classVariableNames: '' |
|||
poolDictionaries: '' |
|||
category: 'Morphic-Basic' |
|||
(Figure "Adding an instance variable".) |
(Figure "Adding an instance variable".) |
||
[Image:instVarAdd.png|right|thumb|Adding an instance variable]] |
[[Image:instVarAdd.png|right|thumb|Adding an instance variable]] |
||
Notice also that the instance variable list in the inspector is |
Notice also that the instance variable list in the inspector is |
||
updated and now you have "timeLimit" variable in the list at the |
updated and now you have "timeLimit" variable in the list at the |
||
Line 273: | Line 289: | ||
self width: 100 / timeLimit. |
self width: 100 / timeLimit. |
||
"step" is an API to make the method |
"step" is an API to make the method execute at a regular interval. |
||
To start it, click on the instance of MyMorph, and drop it again. |
To start it, click on the instance of MyMorph, and drop it again. |
||
This triggers the World to recognize the dropped morph expects step to |
This triggers the World to recognize the dropped morph expects step to |
||
be called. Look at the value in the inspector, and see it |
be called. Look at the value in the inspector, and see it decrease |
||
by one at every second. Also, the width of MyMorph instance changes. |
by one at every second. Also, the width of MyMorph instance changes. |
||
Line 291: | Line 307: | ||
The wonderful thing about Smalltalk is that the debugger and code is |
The wonderful thing about Smalltalk is that the debugger and code is |
||
"live". An error happened because we are |
"live". An error happened because we are silly enough to divide a |
||
number by zero. Perhaps division is not |
number by zero. Perhaps division is not the right thing. Edit the |
||
method shown "in" the debugger, so that it reads: |
method shown "in" the debugger, so that it reads: |
||
step |
step |
||
timeLimit := timeLimit - 1. |
|||
self width: 100 - timeLimit. |
|||
self width: 100 - timeLimit. |
|||
and accept it right there. The system keep all the stack frames |
and accept it right there. The system keep all of the stack frames up to |
||
this method invocation and restart the accepted method right from |
this method invocation and restart the accepted method right from |
||
there. Click on the "proceed" button in the debugger, and pick up and |
there. Click on the "proceed" button in the debugger, and pick up and |
||
Line 308: | Line 323: | ||
If you want to look at what you did, go back to to the Browser and |
If you want to look at what you did, go back to to the Browser and |
||
while the definition of step is shown, click on the "versions" button. |
while the definition of step is shown, click on the "versions" button. |
||
You see |
You see the history of all of the methods, which is kept in the .changes |
||
file. |
file. |
||
Save your .image whenever you think it makes sense. |
Save your .image whenever you think it makes sense. |
||
== |
== Troubleshooting == |
||
A few life savers are good to know. If you happen to get into an |
A few life savers are good to know. If you happen to get into an |
||
infinite loop and the system seems to be locked up, hit Alt-. (i.e., |
infinite loop and the system seems to be locked up, hit Alt-. (i.e., |
||
Line 323: | Line 338: | ||
system doesn't respond anymore and you cannot even save the image. Is |
system doesn't respond anymore and you cannot even save the image. Is |
||
all your work since last save is lost? Yes and no. At least, all |
all your work since last save is lost? Yes and no. At least, all |
||
method |
method changes, class definition changes, and do it are logged into the |
||
.changes file, and the tools under "changes..." menu, such as "recent |
.changes file, and the tools under "changes..." menu, such as "recent |
||
logged changes..." can bring them back. |
logged changes..." can bring them back. |
||
See also the [[Etoys_Tips_and_Tricks]] page for... well... tips and tricks. |
|||
== Submit your changes == |
== Submit your changes == |
||
Line 335: | Line 352: | ||
Get |
Get |
||
the context menu for the top-left pane, and choose rename. Give a |
the context menu for the top-left pane, and choose rename. Give a |
||
proper name |
proper name to your changes (here, let us say it is "myChanges"). |
||
Then get the context menu again and click on "file out (o)". The |
Then get the context menu again and click on "file out (o)". The |
||
textual representation of your work is written to disk. The file name |
textual representation of your work is written to disk. The file name |
||
will be "myChanges.cs". Email |
will be "myChanges.cs". Email myChanges.cs to etoys-dev@squeakland.org, |
||
or |
or attach them to a tracker ticket (http://tracker.squeakland.org/). The core |
||
developers are using the exact same mechanism. The "official" changes |
developers are using the exact same mechanism. The "official" changes |
||
are uploaded to http:// |
are uploaded to http://etoys.squeak.org/updates and all |
||
developers can fetch them via "update code from server" in "help..." |
developers can fetch them via "update code from server" in "help..." |
||
menu. There are some styles in code, organization of methods and |
menu. There are some styles in code, organization of methods and |
||
classes, and description (preamble and postscript) of changesets. If |
classes, and description (preamble and postscript) of changesets. If |
||
you are interested in, browse these files on the web and also fetch |
you are interested in, browse these files on the web and also fetch |
||
the real developers version of image from http:// |
the real developers version of image from http://etoys.squeak.org/download |
||
The real version has larger .changes file with all of last 5-6 years |
|||
of history. Also, all changes sets are available in the image. |
|||
== Final Words == |
== Final Words == |
||
I didn't |
I didn't mention the features of Browser that let you navigate |
||
through the |
through the interrelated methods in a way you navigate through |
||
hyperlinked text. |
hyperlinked text. I didn't mention about the profiler, nor all the |
||
protocols of the Morphic GUI framework, nor various ways of finding a |
protocols of the Morphic GUI framework, nor various ways of finding a |
||
method that would do what you want (try method finder in the "open..." |
method that would do what you want (try method finder in the "open..." |
||
menu.). Please explore and make great and fun applications, |
menu.). Please explore and make great and fun applications, enhancements, |
||
and share them with us. Please send questions to the etoys mailing list. |
|||
it to etoys mailing list. |
|||
== External Resources == |
|||
http://squeakbyexample.org/ Here you will find a great book about programming with Squeak. |
|||
[[category:software development]] |
Latest revision as of 19:23, 22 June 2010
General Introduction
The Etoys activity installed on XO is written in the Squeak Smalltalk system. Etoys pretends to be an application for end-users, but it is just a kids' playground guarded by soft fences, so to speak. Once you make a hole on the fences and get outside, you will have access to a full-fledged, general purpose, multimedia ready, integrated development environment. One of unique aspects of Etoys is that all files that the core developers of the activity uses are shipped with XO; this means that even if the only computer you have is the XO, you can develop as much as any of the core developers do with Etoys, and if you prove that you are good, you can be a core developer of the default activity on XO. Sounds exciting?
On this page, I'll explain how to disable the fences, write code, save
your changes and share it.
Set up Your Files
First, you copy two files from /usr/share/etoys to a location where the user "olpc" can write. Follow the steps described below:
Do either one of following two options (2.1 "Copy Files to /media" or 2.2 "Use USB memory"). If you don't have a USB memory handy or you would like to do it without one, do 2.1. Otherwise, do 2.2.
Copy Files to /media
Open the "Console" activity. and execute the following commands:
% su # mkdir -p /media/foo/olpc-dev # chown olpc:olpc /media/foo/olpc-dev # chmod 777 /media/foo/olpc-dev # cd /usr/lib/squeak/3* # ln -s ../../../share/etoys/EtoysV3.sources # exit % cp /usr/share/etoys/etoys.{image,changes} /media/foo/olpc-dev % chmod 666 /media/foo/olpc-dev/etoys*
Use USB memory
- Plug your USB memory into a slot, start the "Console" activity and execute the following:
% cd /media/* % mkdir olpc-dev % cp /usr/share/etoys/etoys.{image,changes} olpc-dev % ln -s /usr/share/etoys/EtoysV3.sources olpc-dev % chmod 666 olpc-dev/etoys.*
(In the first option, you could make the symbolic link to /usr/share/etoys/EtoysV3.sources from the location where your etoys.image will reside. In a future version, we would include the symbolic link from /usr/lib/squeak/3.9-12 or such automatically.)
Note that your USB memory must be formatted with a filesystem that can support symbolic links, such as ext2 or ext3. Also, the mountpoint must be writable by user "olpc", or else the Journal activity will not recognize the external storage. (Journal will attempt to create a directory .olpc.store in the root of the storage device to host its metadata. Once this is created with the proper permissions, perhaps the mountpoint could revert to ownership by root.) If your USB memory is not formatted to support symbolic links and there is enough space on the USB memory device, you can just copy the EtoysV3.sources file instead of making a symbolic link.
As you might see, the purpose of this step is to make a copy of etoys.image and etoys.changes and put them under /media/vol-name/olpc-dev, make the directory writable, and put writable copies of etoys.image and etoys.changes in the directory.
If you can read a shell script, take a look at /usr/bin/etoys. The ALTIMG variable specifies where to look for alternate .image. You could edit the shell script and specify your own .image file anywhere in the file system.
Start Up Etoys and Change Preferences
Now, bring up the Sugar frame (either going to the donut view or press the frame button), and click on the shooting star to launch Etoys. Since the .image is an exact copy of the default one so far, you might not see whether your image is launched or not. First, you need to know how to break in the fences put around Etoys. What we would like to do is to turn off "eToyFriendly" preference and set up a few other things.
- Press, Alt-, (i.e., hold the Alt key first, and while you are holding it, hit "," key and then release Alt key) or (if we fix a bug) do the "show source" gesture. You'll get a menu that looks like Figure "Show Source".
- From the menu, choose 'help...' and 'preferences...'. Depending on the language setting, these menu items may be translated. But you should be able to figure them out. You get a Preference Panel that looks like Figure "Preferences Panel".# In the Preference Panel, click on the button labeled "scripting", and uncheck "eToyFriendly" box. This may take 10 seconds or so; be patient.
- After it is done, now you can bring up the vital "World menu" by just clicking on the empty area of screen. The World menu looks like Figure "The World Menu".
- Now, try to choose "save" (fifth from the bottom). If the .image you are on is indeed the writable one, it will update the .image and .changes files on the disk. If you do not see a pink small dialog pops up but the cursor changes to a pen-shape momentarily, the files are successfully saved. If you see a pink dialog, go back to the previous section and make sure you are doing it right. (If you know how to get a Workspace, try to evaluate expressions like "Smalltalk imagePath".)
- For what we are going to do (write your own code), having a car running around in front of you may be disturbing (either a virtual car or real car). Get the World menu again, and choose "previous project" at the top. You'll be taken to an empty project, which is more suitable to do the following and more. Save your image again after that.
There are a few other preferences you might want to change. One is "swapControlAndAltKeys"; this is "on" by default so that basic code editing short cut keys use the ctrl key. You could set this to off to be compatible with other platforms, but there is a catch. Sugar intercepts some of the Alt-key combinations so this can be very dangerous. For example, when you press Alt-c to mean to copy text, Sugar interprets it as quit and kills your Squeak session. Another preference is "swapMouseButtons" preference. During development, you would rather use the right mouse button to bring up context menus rather than the halo. (If you turn it on, do Alt-click on a widget to get the halo.)
Assuming you can save your image file, this is a good time to "fetch updates" into your image. The core developers make the changes to the official image in a form of downloadable files (which is explained below) and if your XO is connected to the Internet, you can fetch them. To do so, get the World menu, click on "help...", and choose "update code from server". If yours is not connected to the Internet, that is okay, just move on.
Here, Let us do "save and quit" from the World menu to save the current Squeak session and have a cup of coffee.
Resuming Session
To resume a previously-saved session, click on the shooting star icon in the Sugar frame. The exact environment you saved will be resumed. (But there is a bug that takes you to the Launcher project. A later version of standard image doesn't do it if eToyFriendly is off.) Yes, Sugar's idea of continuous running activities you only suspend and resume have a root in this Smalltalk's idea. However, beware of a difference; Squeak does not save its image automatically upon exit. You even have an option to say "quit", to mean "quit without save".
You can also copy your .image and .changes pair to a non-XO environment (Windows, Mac, Linux or two dozen of other different kinds of platforms) and resume the session on it. The screen extent may be different on a different computer but otherwise the exact state, including all running processes comes back.
From the Console activity, you can launch a Squeak session by executing:
% squeak your-favorite.image
(There are some command line options you might want to provide. see /usr/bin/etoys if you want to follow what it does.)
You could also write a one-liner shell script to add these options. (Yes, in fact, we should change /usr/bin/etoys so that when an argument .image is specified, it uses that image.)
Basic Programming Tools
Describing the full details of Smalltalk development techniques is not the scope of this page, but I will describe some basics.
From the 'open...' menu in the World menu, you can access the most important tools. Transcript ('transcript (t)') is always handy. Get one, resize it to a fairly small size (a height enough for 5 lines or such is usually ok). Equally handy is a Workspace. Get one from 'workspace (k)' menu item. In there, type "3 + 4", put the text insertion cursor on the line, get the context menu (by right-clicking on the pane, or if swapMouseButtons is not set, click on a square button above the vertical scroll bar), and choose "print it (p)". It executes the expression and prints the result. (See Figure "Workspace and Transcript".)
The main programming tool in Squeak is "System Browser", which is available from 'browser (b)' menu item in 'open...'. (You rarely need to instantiate a Browser from the menu. Because you have one or any other text pane opened, you can instantiate more from it with keyboard short cuts.) (See Figure "System Browser".)
In the Browser, let us define a subclass of "RectangleMorph" called "MyMorph". (Squeak's default GUI framework is called "Morphic". And, graphical entities on screen are subinstances of Morph.) Get a context menu in the top-left pane. From the menu, choose "find class... (f)" and type, "Rectan" or such and hit the enter key. From the list, choose "RectangleMorph" (Figure "Find a class").
You might want to resize the Browser. In the second from bottom pane, you see text that looks like:
BorderedMorph subclass: #RectangleMorph instanceVariableNames: classVariableNames: poolDictionaries: category: 'Morphic-Basic'
Replace it with
RectangleMorph subclass: #MyMorph instanceVariableNames: classVariableNames: poolDictionaries: category: 'Morphic-Basic'
Get the context menu in the pane and choose "accept (s)". (See Figure "Defining a class".)
Notice that the red borders of the pane go away, and an item "MyMorph" shows up in the second pane from the left. You successfully created a class in Squeak.
Let us define a method. Click on the "-- all--" line in the third pane. The bottom pane will show the method template (See Figure "Method Template").
message selector and argument names "comment stating purpose of message" | temporary variable names | statements
Here, you just replace it with something like:
initialize
super initialize. self color: Color green.
and choose "accept (s)" from the context menu. Now, you define the initialize method for a instance of the class. (See Figure "Defining a Method".)
Go to the Workspace you might have already opened, and type:
m := MyMorph new. m openInHand.
Select these two lines, get the context menu for the workspace and choose "do it (d)" or "print it (p)", you get a green rectangle attached to the mouse cursor. Drop it somewhere visible. (Figure "Evaluation in Workspace".)
In the workspace, the instance on the screen is bound to a workspace variable "m". Evaluate lines like:
m color: Color red. m width: 100. m height: 100. m borderWidth: 10.
etc. You can select and "do it" each line at a time, or select many lines and execute them like a method.
Similar things can be done from an "inspector". Alt-click on the instance of MyMorph on screen to get halo. With "eToyFriendly" preference off, you have an extra handle that looks like a wrench (See Figure "Debug Handle".)
Click on it, and choose "inspect morph" from the menu you get. On the left, there is a list of instance variables including inherited ones. If you select one, the printed representation of the value bound to the instance variable is shown on the right. You can edit there, and accept it. A value created from the string is stored into the instance variable. The bottom pane can be used as a Workspace, except the fact that its "context" is set to the MyMorph instance. Namely, 'self' refers to the instance, and all instance variable names are usable to use the current values in them.
For doing a fun experiment, let's add an instance variable to MyMorph. Go back to Browser, and click on the "instance" button below the second pane. You'll go back to the "class definition" of MyMorph that looks like:
RectangleMorph subclass: #MyMorph instanceVariableNames: classVariableNames: poolDictionaries: category: 'Morphic-Basic'
Put the text selection cursor in between the single quotes after instanceVariableNames:, and type in "timeLimit", and accept. The red-borders goes away again, and the class definition looks like:
RectangleMorph subclass: #MyMorph instanceVariableNames: 'timeLimit' classVariableNames: poolDictionaries: category: 'Morphic-Basic'
(Figure "Adding an instance variable".)
Notice also that the instance variable list in the inspector is updated and now you have "timeLimit" variable in the list at the bottom. Choose it and set a value like 20 in the right pane, and accept it. (Figure "Set value to instance variable from inspector".)
Go back to the Browser, click on "-- all --" again. Replace the method template with:
step timeLimit := timeLimit - 1. self width: 100 / timeLimit.
"step" is an API to make the method execute at a regular interval. To start it, click on the instance of MyMorph, and drop it again. This triggers the World to recognize the dropped morph expects step to be called. Look at the value in the inspector, and see it decrease by one at every second. Also, the width of MyMorph instance changes.
20 seconds later, timeLimit becomes zero, and in the step method, you will get an error because you divide a number by zero. What happens? You will see a small pink window called notifier that shows the list of stack frames that ends up with the error. (Figure "Error Notifier".)
Click on the second from top that reads "MyMorph>>step" and you get a bigger window that looks like Figure "Debugger".
The part "/ timeLimit" is highlighted. That is the message currently executing in the frame.
The wonderful thing about Smalltalk is that the debugger and code is "live". An error happened because we are silly enough to divide a number by zero. Perhaps division is not the right thing. Edit the method shown "in" the debugger, so that it reads:
step timeLimit := timeLimit - 1. self width: 100 - timeLimit.
and accept it right there. The system keep all of the stack frames up to this method invocation and restart the accepted method right from there. Click on the "proceed" button in the debugger, and pick up and drop the rectangle again. The system is fine with such on-the-fly editing. (Figure "Fixing code in the Debugger".)
If you want to look at what you did, go back to to the Browser and while the definition of step is shown, click on the "versions" button. You see the history of all of the methods, which is kept in the .changes file.
Save your .image whenever you think it makes sense.
Troubleshooting
A few life savers are good to know. If you happen to get into an infinite loop and the system seems to be locked up, hit Alt-. (i.e., hold down the Alt-key, and hit the period key). You can interrupt the process.
Inevitably, you may end up with breaking the system, by redefining or removing some crucial method or system object. In that case, the system doesn't respond anymore and you cannot even save the image. Is all your work since last save is lost? Yes and no. At least, all method changes, class definition changes, and do it are logged into the .changes file, and the tools under "changes..." menu, such as "recent logged changes..." can bring them back.
See also the Etoys_Tips_and_Tricks page for... well... tips and tricks.
Submit your changes
After writing a fun program, you probably would want to share what you wrote. In the "changes..." and "open..." menu, there is a tool called Change Sorter (Figure "Change Sorter".)
Get the context menu for the top-left pane, and choose rename. Give a proper name to your changes (here, let us say it is "myChanges"). Then get the context menu again and click on "file out (o)". The textual representation of your work is written to disk. The file name will be "myChanges.cs". Email myChanges.cs to etoys-dev@squeakland.org, or attach them to a tracker ticket (http://tracker.squeakland.org/). The core developers are using the exact same mechanism. The "official" changes are uploaded to http://etoys.squeak.org/updates and all developers can fetch them via "update code from server" in "help..." menu. There are some styles in code, organization of methods and classes, and description (preamble and postscript) of changesets. If you are interested in, browse these files on the web and also fetch the real developers version of image from http://etoys.squeak.org/download
Final Words
I didn't mention the features of Browser that let you navigate through the interrelated methods in a way you navigate through hyperlinked text. I didn't mention about the profiler, nor all the protocols of the Morphic GUI framework, nor various ways of finding a method that would do what you want (try method finder in the "open..." menu.). Please explore and make great and fun applications, enhancements, and share them with us. Please send questions to the etoys mailing list.
External Resources
http://squeakbyexample.org/ Here you will find a great book about programming with Squeak.