<div dir="ltr">I've been working on a project off and on over the last year called superDoit[1]. I'm headed towards a v2.0 release soonish, but here is an example script[2].<div><br></div><div>I think the cool features are that you can declare script args and embed the help text in the script. No funky handling of $' when you try to write help in a smalltalk method:). You can have script methods and script instance variables (here's my kitchen sink example script[2]) ... the supporting code simple mashes the different sections together and creates a class that is executed in the image.</div><div><br></div><div><div>The script can be imported into an image where you can work on the class in a Browser and then export the script back in superDoit format ...</div><div><br></div><div>I'm even using superDoit to drive github actions for Rowan-based projects[3] ... As an aside I intend to add Rowan support to SmalltalkCI, but I was able to get the superDoit-based github actions written in a week :) </div><div><br></div></div><div>Here's an example of the simplest superDoit script:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">rogue:~>cat simplest.solo<br>#!/usr/bin/env superdoit_solo<br>usage<br>-----<br>USAGE $basename [--help | -h] [--debug | -D]<br>%<br>doit<br>      ^ 3 + 4<br>%<br>rogue:~>./simplest.solo -h<br>-----<br>USAGE simplest.solo [--help | -h] [--debug | -D]<br>rogue:~>./simplest.solo<br>7<br></blockquote><div>and here's an example of using the debugger with a "simplest script" (topaz is the GemStone command line debugger, but it would be relatively straightforward to arrange the a Squeak image debugger to be invoked):</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> rogue:~>cat debug.solo<br>#!/usr/bin/env superdoit_solo<br>usage<br>-----<br>USAGE $basename [--help | -h] [--debug | -D]<br>%<br>doit<br>     ^ 3 foo<br>%<br>rogue:~>./debug.solo -D<br>-----------------------------------------------------<br> Near line 62 of file /home/dhenrich/rogue/_homes/rogue/_home/shared/repos/superDoit/gemstone/superdoit.tpz<br>GemStone: Error         Nonfatal<br>a MessageNotUnderstood occurred (error 2010), a SmallInteger does not understand  #'foo'<br>Error Category: 231169 [GemStone] Number: 2010  Arg Count: 4 Context : 20 exception : 104267265<br>Arg 1: [104268801 size:3 primitiveSize:3 cls: 110849 Symbol] foo<br>Arg 2: [2 size:0 primitiveSize:0 cls: 74241 SmallInteger] 0 == 0x0<br>Arg 3: [26 size:0 primitiveSize:0 cls: 74241 SmallInteger] 3 == 0x3<br>Arg 4: [104266497 size:0 primitiveSize:0 cls: 66817 Array] anArray<br>Stopping at line 62 of /home/dhenrich/rogue/_homes/rogue/_home/shared/repos/superDoit/gemstone/superdoit.tpz<br>topaz 1> where<br>==> 1 MessageNotUnderstood >> defaultAction         @2 line 3   [methId 5550337]<br>2 MessageNotUnderstood (AbstractException) >> _signalWith: @5 line 25   [methId 3805953]<br>3 MessageNotUnderstood (AbstractException) >> signal @2 line 47   [methId 3818753]<br>4 SmallInteger (Object) >> doesNotUnderstand:   @9 line 10   [methId 6465537]<br>5 SmallInteger (Object) >> _doesNotUnderstand:args:envId:reason: @8 line 14   [methId 6430209]<br>6 Executed Code                                 @2 line 1   [methId 104259073]<br>7 GsNMethod >> _executeInContext:               @1 line 9   [methId 5777921]<br>8 String >> evaluateInContext:symbolList:       @3 line 10   [methId 6208001]<br>9 SuperDoitExecutionClass (SuperDoitExecutionMetadataClass) >> theDoit @4 line 2   [methId 104255233]<br>10 [] in SuperDoitExecution >> doit              @12 line 7   [methId 104192769]<br>11 ExecBlock0 (ExecBlock) >> on:do:              @3 line 44   [methId 5921281]<br>12 SuperDoitExecutionClass (SuperDoitExecution) >> doit @2 line 8   [methId 104309761]<br>13 SuperDoitDoitCommand >> executeAgainst:       @27 line 19   [methId 104250625]<br>14 [] in SuperDoitCommandDefinition >> executeAgainst: @7 line 2   [methId 104191233]<br>15 OrderedCollection (Collection) >> do:         @5 line 10   [methId 3486465]<br>16 SuperDoitCommandDefinition >> executeAgainst: @3 line 2   [methId 104159745]<br>17 [] in SuperDoitCommandParser >> parseAndExecuteScriptFile: @22 line 15   [methId 104158465]<br>18 [] in AbstractFileReference >> readStreamDo:  @8 line 4   [methId 47039745]<br>19 ExecBlock0 (ExecBlock) >> ensure:             @2 line 12   [methId 5912577]<br>20 FileReference (AbstractFileReference) >> readStreamDo: @4 line 5   [methId 42107137]<br>21 SuperDoitCommandParser >> parseAndExecuteScriptFile: @2 line 3   [methId 104154113]<br>22 SuperDoitCommandParser class >> processInputFile @31 line 22   [methId 104165889]<br>23 Executed Code                                 @2 line 6   [methId 104189185]<br>24 GsNMethod class >> _gsReturnToC               @1 line 11   [methId 5750785]<br>  [GsProcess 104313089]<br>topaz 1> </blockquote><div><br></div><div>The project was aimed at GemStone, but there are chunks of code that are definitely platform independent and I'd be willing to collaborate with someone from the Squeak community to add Squeak support, if anyone wanted to build a Squeak variant of superDoit ...</div><div><br></div><div>The shebang script (#!/usr/bin/env superdoit_solo[4]) is pretty simple and would probably be even simpler for Squeak :)</div><div><br></div><div>Dale <br><div><br></div><div>[1] <a href="https://github.com/dalehenrich/superDoit/tree/v2.0#superdoit\">https://github.com/dalehenrich/superDoit/tree/v2.0#superdoit\</a></div><div>[2] <a href="https://github.com/dalehenrich/superDoit/blob/v2.0/examples/kitchenSink/commonCommandExample.stone">https://github.com/dalehenrich/superDoit/blob/v2.0/examples/kitchenSink/commonCommandExample.stone</a></div></div><div>[3] <a href="https://github.com/GsDevKit/OrderedDictionary/blob/rowanize/.github/workflows/ci.yml#L24-L36">https://github.com/GsDevKit/OrderedDictionary/blob/rowanize/.github/workflows/ci.yml#L24-L36</a></div><div>[4] <a href="https://github.com/dalehenrich/superDoit/blob/v2.0/bin/superdoit_solo">https://github.com/dalehenrich/superDoit/blob/v2.0/bin/superdoit_solo</a></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Nov 18, 2021 at 9:27 AM Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
> On Nov 18, 2021, at 2:50 AM, Tony Garnock-Jones <<a href="mailto:tonyg@leastfixedpoint.com" target="_blank">tonyg@leastfixedpoint.com</a>> wrote:<br>
> <br>
> Heh! Yeah, it could be done from a Squeak with OSProcess loaded. (Part of why I picked chunks as the Squeakerfile format...)<br>
> <br>
> The utility of docker containers is that they can be wired together. We don't have a good story for wiring together Smalltalk images yet. Weird, huh?<br>
> <br>
> So yeah, not until there's some way of *talking* to a running image that doesn't involve *being inside it* will there be much use to an image library, or a squeaker-compose-like thing...<br>
<br>
There are already a few ways:<br>
- command-line arguments<br>
- reading from stdin<br>
- drop events/launch events<br>
- reading (eg an ini) file(s)<br>
- a socket server<br>
<br>
And it would be easy to build a Squeak scripting engine scheme that would treat #!squeak appropriately <br>
<br>
> Cheers,<br>
>  Tony<br>
> <br>
>> On 11/18/21 10:47 AM, Thiede, Christoph wrote:<br>
>> Nice idea! One could call it a bit pity that you had to write this in Python rather than in Squeak itself, but it is the result tthat counts. :-)<br>
>> Next up: Squeaker Hub, squeaker-compose, and integrated CI support for Squeaker images? :D<br>
>> Best,<br>
>> Christoph<br>
>> ------------------------------------------------------------------------<br>
>> *Von:* Squeak-dev <<a href="mailto:squeak-dev-bounces@lists.squeakfoundation.org" target="_blank">squeak-dev-bounces@lists.squeakfoundation.org</a>> im Auftrag von Tony Garnock-Jones <<a href="mailto:tonyg@leastfixedpoint.com" target="_blank">tonyg@leastfixedpoint.com</a>><br>
>> *Gesendet:* Donnerstag, 18. November 2021 09:42:23<br>
>> *An:* The general-purpose Squeak developers list<br>
>> *Betreff:* [squeak-dev] [ANN] Squeaker: Like Docker, but for Squeak. You know, for kids.<br>
>> I found myself in need of a way to script the production of clean images<br>
>> customised by some sequence of Smalltalk commands. ("Cattle, not pets.")<br>
>> Presto,<br>
>> <a href="https://github.com/tonyg/squeaker" rel="noreferrer" target="_blank">https://github.com/tonyg/squeaker</a> <<a href="https://github.com/tonyg/squeaker" rel="noreferrer" target="_blank">https://github.com/tonyg/squeaker</a>><br>
>>  From the README (<a href="https://github.com/tonyg/squeaker#readme" rel="noreferrer" target="_blank">https://github.com/tonyg/squeaker#readme</a> <<a href="https://github.com/tonyg/squeaker#readme" rel="noreferrer" target="_blank">https://github.com/tonyg/squeaker#readme</a>>):<br>
>> ====<br>
>> It's a small program that helps in automated derivation of configured<br>
>> Smalltalk images from some fixed base image and a collection of<br>
>> Smalltalk commands. It's about 500 lines of Python, so far.<br>
>>   - Squeakerfile.st is like Dockerfile, except it contains locations to<br>
>> fetch images from plus Smalltalk expressions to derive new images.<br>
>>   - squeaker build is like docker build. It manages a cache (in<br>
>> $XDG_CACHE_HOME/squeaker, usually $HOME/.cache/squeaker on Unix) of<br>
>> downloaded artifacts, derived images, and the stages in each derivation.<br>
>>   - squeaker run is like docker run. It starts a previously-downloaded<br>
>> or -derived image in a temporary directory. (Future: support persistent<br>
>> image instances, like docker does! Easy enough.)<br>
>>   - squeaker gc is like docker system prune, roughly. It cleans out the<br>
>> Squeaker cache directory, treating tags as GC roots.<br>
>> ====<br>
>> Please try it out and let me know what you think!<br>
>> Cheers,<br>
>>    Tony<br>
> <br>
<br>
</blockquote></div>