stash

Description

smalltalk shell - new life for an old idea (http://seaside.gemtalksystems.com/ss/stash.html)

Details

Source
GitHub
License
MIT
Stars
1
Created
April 2, 2019
Updated
Nov. 21, 2021

Categories

Web

README excerpt

# Stash
Shell interpreters for [GemStone/S 64 smalltalk][1] and [topaz][2].

Stash makes it possible to directly execute standalone topaz and smalltalk scripts.

Note that **GemStone/S 64 3.5.0** or later is required.
### topaz script
Here is a [`hello world` topaz script][3]:
```smalltalk
#!/usr/local/bin/smalltalk/gemstone/topaz
#
#	Write `hello world` to stdout and exit.
#
login
run
	GsFile stdout nextPutAll: 'hello world'
%
exit
```
### smalltalk doit script
Here is a [`hello world` doit script][15]:
```smalltalk
#!/usr/local/bin/smalltalk/gemstone/smalltalk

GsFile stdout nextPutAll: 'hello world'; lf
```

### stash script

Here is a [`hello world` stash script][4]:
```smalltalk
#!/usr/local/bin/smalltalk/gemstone/stash
"
	Write `Hello World` to stdout and exit.
"
Class {
     #name : 'HelloWorldScript',
     #superclass : 'StashScript',
     #category : 'Stash-Scripts'
}

{ #category : 'script execution' }
 HelloWorldScript>> executeScript [

	opts at: 'help' ifPresent: [ ^ self usage ].
	GsFile stdout nextPutAll: 'Hello World'; lf
]

{ #category : 'usage' }
 HelloWorldScript>> usage [

	self usage: 'hello.st' description: 'Write `hello world` to stdout and exit.'
]
```
### Table of Contents
1. [Script execution environment](#script-execution-environment)
2. [Installation](#installation)
3. [Examples](#examples)
4. [Creating your own scripts](#creating-your-own-scripts)
5. [Debugging scripts](#debugging-scripts)
6. [Topaz Solo script support](#topaz-solo-script-support)
# Script execution environment
Stash scripts are executed in a GemStone session that is running against a 
particular GemStone Object Server or against a single user GemStone extent
file, using a topaz solo login (see 
[Topaz Solo script support](#topaz-solo-script-support) for more info).
A combination of environmentvariables and command line arguments are used to
select the desired execution environment.
There are two execution environments that are currently supported:
1. [Classic GemStone](#classic-gemstone-environment)
2. [GsDevKit_home](#gsdevkit_home-environment)

## Classic GemStone environment
The **Classic GemStone** environment expects:
1. The **GEMSTONE** environmnent variable to refence the GemStone/S 64 product
tree to be used.
2. The **PATH** environment variable to reference `$GEMSTONE/bin`, where the `topaz` executable is located.
3. and a [`.topazini` file][5] to specify the name of the GemStone Object Server to be used, 
as well as the the userId, and password to be used to create GemStone session to execute the script.
### topaz script invocation
A command line invocation of the `hello.tpz` script using the 
[classic GemStone environment](#classic-gemstone-environment) would look like the following:
```bash
bash> hello.tpz -lq -I ./.topazini
hello world
```
### doit script invocation
A command line invocation of the `hello.st` script using the 
[Classic GemStone environment](#classic-gemstone-environment) would look like the following:
```bash
bash> hello.st -- -lq  -I ./.topazini
Hello World
```
## GsDevKit_home environment
The **GsDevKit_home** environment expects:
1. The **GS_HOME** environmnet variable to reference the root directory of the 
[GsDdevKit_home][6] installation.
2. The name of the stone is enough to identify where the GemStone/S 64 product
tree is located as well as where the default [`.topazini` file][5] is located.
### topaz script invocation
A command line invocation of the `hello.tpz` script using the 
[GsDevKit_home environment](#gsdevkit_home-environment) would look like the following:
```bash
bash> hello.tpz <stone-name> -lq
hello world
```
### doit script invocation
A command line invocation of the `hello.st` script using the 
[GsDevKit_home environment](#gsdevkit_home-environment) would look like the following:
```bash
bash> hello.st -- <stone-name> -lq
Hello World
```
# Installation 
To install Stash, you need to have `sudo` privileges, as the shell interpreters
([smalltalk_350_interpreter][7] and [topaz_350_interpreter][8]) need to be
installed in `/usr/local/bin/smalltalk/gemstone`.

Stash will install [Rowan][10] into your stone as it is required.
The Rowan environment needs to have the **ROWAN_PROJECTS_HOME** environment 
variable defined. 
**ROWAN_PROJECTS_HOME** defines the directory where the git clones for stash
and Rowan will be located.

## Classic GemStone install
For a [Classic GemStone installation](#classic-gemstone-install), you need to have the
environment variables set up and create a stone that will be used to provide
the the scripting environment. You will supply the name of the stone on the 
[`install.sh`][9] command line:
```bash
export ROWAN_PROJECTS_HOME=<git-clone-directory>
cd $ROWAN_PROJECTS_HOME
git clone https://github.com/dalehenrich/stash.git
$ROWAN_PROJECTS_HOME/stash/bin/install.sh <stone-name>
```

## GsDevKit_home install
For a [GsDevKit_home installation](#gsdevkit_home-install), you need to have `$GS_HOME`
defined. You do not need to have a stone created before running the 
[`install.sh`][9] script.
If you provide the GemStone/S 65 version number on the command line, the script
will create the stone for you:
```bash
export ROWAN_PROJECTS_HOME=$GS_HOME/shared/repos
cd $ROWAN_PROJECTS_HOME
git clone https://github.com/dalehenrich/stash.git
$ROWAN_PROJECTS_HOME/stash/bin/install.sh <stone-name> 3.5.0
```
# Examples
There are a number of scripts in the [`$ROWAN_PROJECTS_HOME/stash/scripts`
directory][13].
Each of the `.st` scripts has a `--help` option defined:
```bash
$ROWAN_PROJECTS_HOME/stash/scripts/snapshot.st --help -- -lq			# GEMSTONE

$ROWAN_PROJECTS_HOME/stash/scripts/snapshot.st --help -- <stone-name> -lq	# GsDevKit_home
```
# Creating your own scripts
### topaz script creation
If you want to create a new topaz script, simply copy the `template.tpz` 
example script and then edit it as needed:
```bash
cp $ROWAN_PROJECTS_HOME/stash/scripts/template.tpz myscript.tpz
```
### stash script creation
To create a new stash script, use the `createTemplateScript.st` script
```bash
$ROWAN_PROJECTS_HOME/stash/scripts/createTemplateScript.st \
	--script=myScript --class=MyScript --dir=/home/me/bin -- MyStone -lq	
```
If take a close look at a stash script, you will notice that this is simply
a Tonel class file and that the class is a subclass of StashScript:
```smalltalk
#!/usr/local/bin/smalltalk/gemstone/stash
"
	Write `Hello World` to stdout and exit.
"
Class {
     #name : 'HelloWorldScript',
     #superclass : 'StashScript',
     #category : 'Stash-Scripts'
}

{ #category : 'script execution' }
 HelloWorldScript>> executeScript [

	opts at: 'help' ifPresent: [ ^ self usage ].
	GsFile stdout nextPutAll: 'Hello World'; lf
]

{ #category : 'usage' }
 HelloWorldScript>> usage [

	self usage: 'hello.st' description: 'Write `hello world` to stdout and exit.'
]
```
The implication here is that this is not just a doit, but a
real live class to which you can add methods and instance variables, etc. 

It is also worth taking a close look at the 
`$ROWAN_PROJECTS_HOME/stash/scripts/rowan.st` script. Specifically, the
`#scriptOptions` and `#executeScript` methods are interesting.
The `#scriptOptions` method is interesting because you can
see an example where a range of command line options, some with 
arguments and some without are declared:
```smalltalk
{ #category : 'script execution' }
rowan >> scriptOptions [
	"specify the command line options"
	^ {
			#('help' $h #none).
			#('install' nil #required).
			#('load' nil #required).
			#('unload' nil #required).
			#('list' nil #none).
			#('write' nil #required).
			#('commit' nil #required).
			#('edit' nil #none).
	}
]
```
The `#executeScript` method because you can see how the various command line 
options are handeled and dispatched:
```smalltalk
{ #category : 'script execution' }
rowan >> executeScript [
	"Called to initiate execution of the script"
	^ opts
			at: 'help'
			ifAbsent: [ 
				opts at: 'edit' ifPresent: [:arg | self edit ].
				opts at: 'install' ifPresent: [:arg | self install: arg ].
				opts at: 'load' ifPresent: [:arg | self load: arg ].
				opts at: 'unload' ifPresent: [:arg | self unload: arg ].
				opts at: 'write' ifPresent: [:arg | self write: arg ].
				opts at: 'commit' ifPresent: [:arg | self commit: arg message: (args at: 1) ].
				opts at: 'list' ifPresent: [:arg | self list ].
				^ true ]
			ifPresent: [ self usage ]
]
``` 
# Debugging scripts
By default if an error occurs during script exection (topaz or smalltalk 
script), script execution halts, the error stack is printed and you are 
left at a topaz command prompt.
### Debugging error
```bash
bash> error.st --boom -- -lq
ERROR 2010 , a MessageNotUnderstood occurred (error 2010), a StashScript class does not understand  #'ansiRedOn:during:' (MessageNotUnderstood)
topaz > exec iferr 1 : stk 
==> 1 MessageNotUnderstood >> defaultAction         @3 line 3
2 MessageNotUnderstood (AbstractException) >> _signalWith: @6 line 25
3 MessageNotUnderstood (AbstractException) >> signal @2 line 47
4 StashScript class (Object) >> doesNotUnderstand: @10 line 10
5 StashScript class (Object) >> _doesNotUnderstand:args:envId:reason: @8 line 14
6 [] in Executed Code                           @10 line 16
7 StashCommandError (AbstractException) >> _executeHandler: @8 line 11
8 StashCommandError (AbstractException) >> _signalWith: @1 line 1
9 StashCommandError (AbstractException) >> signal: @3 line 7
10 StashCommandError class (AbstractException class) >> signal: @3 line 4
11 ErrorExampleScript (StashScript) >> error:    @2 line 3
12 [] in ErrorExampleScript >> executeScript     @14 line 6
13 ExecBlock0 (ExecBlock) >> cull:               @5 line 7
14 Dictionary (AbstractDictionary) >> at:ifPresent: @5 line 7
15 [] in ErrorExampleScript >> executeScript     @7 line 6
16 Dictionary (AbstractDictionary) >> at:ifAbsent:ifPresent: @4 line 6
17 ErrorExampleScript >> executeScript           @3 line 4
18 ErrorExampleScript (StashScript) >> setupAndExecuteScript @
← Back to results