In the meantime, I figured out that the Smalltalk globals environment
does not export anything. Hence, nothing can be imported from it by
default.
Further, I found this post [1] by Frank Shearar, which contains a
snippet to load a package into an environment (however,
EnvironmentRequest has been renamed to CurrentEnvironment since then).
He also proposes `Smalltalk globals exportSelf` there, to let the
global environment export its contents, which could be one way to
solve my first problem.
I am unsure how this is intended to be used; what is the reason for
not letting the global environment export anything by default? After
all, you have to start somewhere... To attempt an alternative, I
created a fresh environment for the classes that I want to import
later under other names like so:
fsenv := Environment named: #FileSystem.
fspackage := PackageOrganizer default packageNamed: 'FS' ifAbsent: [].
fspackage classes do: [:ea | fsenv bind: ea name to: ea ]
fsenv importSelf.
fsenv exportSelf.
testenv := Environment named: #TestEnv1.
testenv importSelf.
testenv exportSelf.
testenv import: fsenv removingPrefix: 'FS'.
testenv valueOf: #Filesystem "=> FSFilesystem"
Now I can use testenv valueOf: #Filesystem to retrieve the
FSFilesystem class, so far so good. I have not used my testenv for
anything real yet, but it is still missing all the basics such as
Object or Array. So I doubt it will be of much use, unless I set up
another environment to import from that contains all the Kernel,
Collections etc. classes. But this does not feel right, as there
already is such an environment: Smalltalk globals...
In the post from 2012 for which Chris posted the link, Colin linked an
image (and luckily, he has not removed it from his webspace since
then) from which I could grab the browser opening snippet. It is
simply
Browser fullOnClass: aClassDefinedInAnotherEnvironment
...which in my case gives me a browser for the global environment
instead, because the "renamed" classes stem from there, of course.
Frank's post also has another snippet to browse an environment:
b := Browser new
selectEnvironment: anEnvironment;
yourself.
Browser openBrowserView: (b openEditString: nil) label: b
defaultBrowserTitle
But it seems like the browser will only show an environment's own
contents, not the imported classes. Hence, I do not see anything in my
environments so far. If my assumption is correct, there is no way to
see the imported classes under their new names in the browser.
When I try to define a new class using my empty browser on my
environment, it goes back into Smalltalk globals and puts the class
there instead. It also does that in Colin's old image, so I guess
defining classes in environments is not supported that way.
More elaborate tools are probably required to easily see what is going
on, without exploring the Environments implementation in parallel.
[1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2013-December/175519…
2016-09-23 11:59 GMT+02:00 Tobias Pape <Das.Linux(a)gmx.de>:
> Hi Colin,
>
> do you have an idea here?
>
> Best regards
> -Tobias
2016-09-16 18:27 GMT+02:00 Chris Cunnington <brasspen(a)gmail.com>:
>>Can I get a system browser for my environment (where saving a method
>>compiles it with the environment bindings in place)?
>
> http://lists.squeakfoundation.org/pipermail/squeak-dev/2012-June/164605.html
>
> Chris
>
> On 16.09.2016, at 14:50, Jakob Reschke <jakob.reschke(a)student.hpi.de> wrote:
>
>> Hello,
>>
>> I am having a look at Environments, but have not yet figured out, how
>> to operate them. I would like to create a new environment with an
>> additional binding for an existing class under another name, and load
>> a package in that new environment.
>>
>> The most of a documentation I have found is http://wiki.squeak.org/squeak/6220
>> and I have tried the following so far:
>>
>> testenv := Environment named: #TestEnv1.
>> testenv import: Smalltalk globals.
>> testenv from: Smalltalk globals import: { #String -> #MyString }.
>> testenv importSelf.
>> testenv exportSelf.
>>
>> However, testenv valueOf: #MyString or testenv valueOf: #String both
>> return nil instead of the String class. Does it mean that the
>> from:import: did not work? It seems to only add a policy to my
>> environment, but no declarations or bindings.
>>
>> For evaluating something in context of the environment, I have found
>> the EnvironmentLoader, but it does not seem to recognize the
>> additional binding either:
>>
>> (EnvironmentLoader for: testenv) evaluate: 'MyString'. => nil
>> (EnvironmentLoader for: testenv) evaluate: 'String'. => nil
>>
>> (at least the import of the original globals seems to have worked).
>>
>> What steps am I missing?
>>
>> Also it is not very convenient to make up strings of code everytime I
>> want to do something in the other environment, is there a better way?
>> Can I get a system browser for my environment (where saving a method
>> compiles it with the environment bindings in place)?
>>
>> Best regards,
>> Jakob
>>
>
Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours:
http://lists.squeakfoundation.org/pipermail/packages/2016-September/068972.…
Name: EToys-tfel.257
Ancestors: EToys-tfel.256
make Kedama worlds copyable, by forcing it to always copy also its patches and turtles, and fixing up the deep copying so these players are copied correctly and their scripts are also recompiled correctly.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2016-September/068973.…
Name: EToys-tfel.258
Ancestors: EToys-tfel.257
- Fix for duplicating KedamaMorphs with non-visible patches or turtles
- be careful not to loose top level projects when deleting projects through the etoys history morph
- setTurtleCount: on a vector player should go to the exampler player
=============================================
Environment carry great promise and potential...
But for now, it's only that.
I recently read "let's fix environments".
+1 too to that generous idea.
But what does it mean?
Without clear goals or vision, fixing could essentially mean "let
Environment be transparent", that is let it remain a promise, a potential,
whithout too many side effects... Not exactly YAGNI, just a bit of
over-engineered nice piece of code that might serve later. OK this sounds
like a mandatory first step.
But then, what feature are we after?
I have read bootstrapping, sandboxing, letting concurrent packages and/or
versions co-exist, stop prefixing class names with pseudo namespace...
So environment are about reducing global variable scope.
For me, the essential decisions are in these questions:
- how will environments and source-code-management interfere?
- how are we going to specify reproducible artifacts (images)?
Are we going to use environment "statically" like in VW, just like
namespaces are in many languages? That somehow means that the SCM will have
to be environment aware.
Or are we going to transfer this responsibility at a higher level, like
Metacello for example? In this later case, we have greater flexibility, but
assembling an image means telling which package is installed into which
environment, then which import are necessary for each environment.
But it's even more complex than that, because the way we create classes: by
subclassing another class. So we don't need one environment, we need at
least two, one source environment for picking the super class, one
destination environment for hosting the subclass. Hmm, the metacello
configuration is going to be verbose...
OK, OK, but how would we designate an environment in the configuration, is
it by name in a sort of Environment registry?
All this is strongly related to Newspeak mechanisms for contructing a
module, http://bracha.org/newspeak-modules.pdf. Newspeak was conceived with
solid foundations. Can we reach a solid design by small iterations? Will we
converge to the same economy of concepts? I just wonder, or should I say
wander?
That's very interesting. So who has a vision?
No urge to asnwer this, let's rather make environment transparent ;)
Nicolas
Tim Felgentreff uploaded a new version of EToys to project The Trunk:
http://source.squeak.org/trunk/EToys-tfel.258.mcz
==================== Summary ====================
Name: EToys-tfel.258
Author: tfel
Time: 28 September 2016, 5:27:37.334594 pm
UUID: ef184947-0831-4b86-9f5f-5707547734bc
Ancestors: EToys-tfel.257
- Fix for duplicating KedamaMorphs with non-visible patches or turtles
- be careful not to loose top level projects when deleting projects through the etoys history morph
- setTurtleCount: on a vector player should go to the exampler player
=============== Diff against EToys-tfel.257 ===============
Item was changed:
----- Method: EToyProjectHistoryMorph>>confirmedDelete:evt:from: (in category 'as yet unclassified') -----
confirmedDelete: aProject evt: evt from: origin
self delete.
aProject = Project current ifTrue: [
^ self inform: 'Cannot delete current project' translated].
(self confirm: ('Do you really want to delete {1}
and all its content?' translated format: {aProject name}))
+ ifTrue: [
+ aProject isTopProject ifTrue: [Project current beTopProject].
+ aProject delete.
+ Project rebuildAllProjects].!
- ifTrue: [aProject delete].!
Item was changed:
----- Method: KedamaMorph>>duplicate (in category 'as yet unclassified') -----
duplicate
| allMorphBounds allMorphs allOwners copyW s w |
allMorphs := {self}, self player allPatchAndTurtleMorphs.
allOwners := allMorphs collect: #owner.
allMorphBounds := allMorphs allButFirst
inject: self bounds into: [:acc :next | next bounds merge: acc].
w := PasteUpMorph new.
w bounds: allMorphBounds.
w openInWorld.
w addAllMorphs: allMorphs.
copyW := w duplicate.
+ allMorphs withIndexDo: [:m :idx | (allOwners at: idx) ifNotNil: [:o | o addMorph: m]].
- allMorphs withIndexDo: [:m :idx | (allOwners at: idx) addMorph: m].
w delete.
s := SelectionMorph new.
s bounds: copyW bounds.
s selectSubmorphsOf: copyW.
^ s!
Item was added:
+ ----- Method: KedamaTurtleVectorPlayer2>>setTurtleCount: (in category 'slot-kedama') -----
+ setTurtleCount: aNumber
+
+ ^ exampler setTurtleCount: aNumber!
Tim Felgentreff uploaded a new version of EToys to project The Trunk:
http://source.squeak.org/trunk/EToys-tfel.257.mcz
==================== Summary ====================
Name: EToys-tfel.257
Author: tfel
Time: 28 September 2016, 2:02:17.012904 pm
UUID: a4bd9831-92ff-fb4f-9f7f-0681429e8add
Ancestors: EToys-tfel.256
make Kedama worlds copyable, by forcing it to always copy also its patches and turtles, and fixing up the deep copying so these players are copied correctly and their scripts are also recompiled correctly.
=============== Diff against EToys-tfel.256 ===============
Item was added:
+ ----- Method: KedamaExamplerPlayer>>veryDeepInner: (in category 'copying') -----
+ veryDeepInner: deepCopier
+ "Special code that handles user-added instance variables of a uniClass.
+ Copy all of my instance variables. Some need to be not copied at all, but shared. This is special code for the dictionary. See DeepCopier."
+
+ kedamaWorld := kedamaWorld veryDeepCopyWith: deepCopier.
+ turtles := turtles veryDeepCopyWith: deepCopier.
+ sequentialStub := sequentialStub veryDeepCopyWith: deepCopier.
+ super veryDeepInner: deepCopier.
+ !
Item was added:
+ ----- Method: KedamaMorph>>duplicate (in category 'as yet unclassified') -----
+ duplicate
+
+ | allMorphBounds allMorphs allOwners copyW s w |
+ allMorphs := {self}, self player allPatchAndTurtleMorphs.
+ allOwners := allMorphs collect: #owner.
+ allMorphBounds := allMorphs allButFirst
+ inject: self bounds into: [:acc :next | next bounds merge: acc].
+ w := PasteUpMorph new.
+ w bounds: allMorphBounds.
+ w openInWorld.
+ w addAllMorphs: allMorphs.
+ copyW := w duplicate.
+ allMorphs withIndexDo: [:m :idx | (allOwners at: idx) addMorph: m].
+ w delete.
+ s := SelectionMorph new.
+ s bounds: copyW bounds.
+ s selectSubmorphsOf: copyW.
+ ^ s!
Item was changed:
----- Method: KedamaMorph>>isVisible: (in category 'private') -----
isVisible: examplerPlayer
| turtleMorph |
turtleMorph := examplerPlayer costume.
turtleMorph visible ifFalse: [^ false].
+ turtleMorph world ifNil: [^ false].
turtleMorph owner isRenderer ifFalse: [^ true].
^ turtleMorph owner visible.
!
Item was changed:
----- Method: KedamaMorph>>offerCostumeViewerMenu: (in category 'menu') -----
offerCostumeViewerMenu: aMenu
aMenu add: 'add a new patch variable' translated action: #newPatch.
aMenu balloonTextForLastItem: 'Add a new patch variable' translated.
aMenu add: 'add a new breed of turtle' translated action: #newTurtle.
aMenu balloonTextForLastItem: 'Add a new turtle' translated.
aMenu addLine.
+ aMenu add: 'gather patches and turtles' translated action: #gatherPatchesAndTurtles.
+ aMenu balloonTextForLastItem: 'Show all turtles next to me' translated.
!
Item was added:
+ ----- Method: KedamaMorph>>patches (in category 'accessing') -----
+ patches
+
+ ^ patchesToDisplay!
Item was added:
+ ----- Method: KedamaMorph>>turtles (in category 'accessing') -----
+ turtles
+
+ ^ turtlesDict keys!
Item was added:
+ ----- Method: KedamaPatchMorph>>veryDeepInner: (in category 'as yet unclassified') -----
+ veryDeepInner: deepCopier
+ "the state of a Kedama patch is held in its forms, so we need to "
+ form := form deepCopy.
+ displayForm := displayForm deepCopy.
+ tmpForm := tmpForm deepCopy.
+ super veryDeepInner: deepCopier.!
Item was added:
+ ----- Method: Player>>allPatchAndTurtleMorphs (in category 'slot-kedama') -----
+ allPatchAndTurtleMorphs
+
+ self costume ifNil: [^ #()].
+ ^ self costume patches, (self costume turtles collect: #costume)!
Item was added:
+ ----- Method: Player>>gatherPatchesAndTurtles (in category 'slot-kedama') -----
+ gatherPatchesAndTurtles
+
+ | position |
+ self costume owner ifNil: [^ self].
+ position := self costume topRight + (5@0).
+ self allPatchAndTurtleMorphs do: [:m |
+ m ifNotNil: [
+ m position: position.
+ self costume owner addMorph: m.
+ m visible: true.
+ position := position + (0@(m height + 5))]].!
Item was added:
+ ----- Method: UniclassScript>>veryDeepFixupWith: (in category 'copying') -----
+ veryDeepFixupWith: deepCopier
+
+ super veryDeepFixupWith: deepCopier.
+ self flag: #todo. "Textually coded scripts may also have to be adapted"
+ Project current addDeferredUIMessage: [
+ "We do this in a deferred way, because the deep copying may non-deterministically
+ be in a state where not all referenced players already have copies, so then we recompile the
+ script, but we still reference the wrong players!! - tfel,jl"
+ self recompileScriptFromTilesUnlessTextuallyCoded].!
On Mon, 26 Sep 2016, commits(a)source.squeak.org wrote:
> Tim Felgentreff uploaded a new version of EToys to project The Trunk:
> http://source.squeak.org/trunk/EToys-tfel.252.mcz
>
> ==================== Summary ====================
>
> Name: EToys-tfel.252
> Author: tfel
> Time: 26 September 2016, 10:06:37.467552 am
> UUID: ec8e5c79-9271-ee4b-b729-a0138c2b4b9d
> Ancestors: EToys-tfel.251
>
> fix a potential bug when the info dictionary for kedama turtle vector players was restored from siss
>
> =============== Diff against EToys-tfel.251 ===============
>
> Item was changed:
> ----- Method: KedamaTurtleVectorPlayer2>>compileAllAccessors (in category 'player protocol') -----
> compileAllAccessors
>
> + info rehash.
> info keys asArray do: [:k |
How about using #keysDo: here?
Levente
> (#(who x y heading color visible predicate) includes: k) ifFalse: [
> self compileVectorInstVarAccessorsFor: k.
> ].
> ].
> !
>
>
>
On Tue, 27 Sep 2016, commits(a)source.squeak.org wrote:
> Tim Felgentreff uploaded a new version of System to project The Trunk:
> http://source.squeak.org/trunk/System-tfel.917.mcz
>
> ==================== Summary ====================
>
> Name: System-tfel.917
> Author: tfel
> Time: 27 September 2016, 2:52:54.264629 pm
> UUID: 6436c2ff-4a02-d845-9b8e-45b8130a609c
> Ancestors: System-bf.916
>
> when trying to load a project from my local server when that is not set, at least try to fall back to the default directory
>
> =============== Diff against System-bf.916 ===============
>
> Item was changed:
> ----- Method: Project>>fromMyServerLoad: (in category 'file in/out') -----
> fromMyServerLoad: otherProjectName
> | pair pr dirToUse |
> "If a newer version of me is on the server, load it."
>
> (pr := Project named: otherProjectName) ifNotNil: ["it appeared"
> ^ pr enter
> ].
> +
> dirToUse := self primaryServerIfNil: [
> + lastDirectory
> + ifNil: [FileDirectory default]
> + ifNotNil: [lastDirectory]].
The #ifNotNil: branch is unnecessary.
Levente
> - lastDirectory ifNil: [
> - self inform: 'Current project does not know a server either.'.
> - ^nil].
> - lastDirectory].
>
> pair := self class mostRecent: otherProjectName onServer: dirToUse.
> pair first ifNil: [^self decideAboutCreatingBlank: otherProjectName]. "nothing to load"
> ^ProjectLoading
> installRemoteNamed: pair first
> from: dirToUse
> named: otherProjectName
> in: self
>
> !
>
>
>