Browse Source

Merge pull request #834 from herby/smalltalk-settings-in-api

Smalltalk settings in api
Nicolas Petton 10 years ago
parent
commit
6bcabeb287
7 changed files with 397 additions and 32 deletions
  1. 11 2
      API-CHANGES.txt
  2. 6 13
      js/Helios-Workspace.js
  3. 2 2
      js/IDE.js
  4. 288 10
      js/Kernel-Infrastructure.js
  5. 2 2
      st/Helios-Workspace.st
  6. 1 1
      st/IDE.st
  7. 87 2
      st/Kernel-Infrastructure.st

+ 11 - 2
API-CHANGES.txt

@@ -28,8 +28,17 @@
 + Set >> removeAll
 + AssociativeCollection class
 + BucketStore class
-+ SmalltalkImage >> globals
-+ SmalltalkImage >> vm
++ SmalltalkImage >>
+  + globals
+  + vm
+  + settings
++ Setting class
++ String >>
+  + asSetting
+  + asSettingIfAbsent:
+  + settingValue
+  + settingValueIfAbsent:
+  + settingValue:
 + Smalltalk global variable
 
 - CompiledMethod >>

+ 6 - 13
js/Helios-Workspace.js

@@ -390,15 +390,11 @@ selector: "editorOptions",
 protocol: 'accessing',
 fn: function (){
 var self=this;
-function $SmalltalkSettings(){return globals.SmalltalkSettings||(typeof SmalltalkSettings=="undefined"?nil:SmalltalkSettings)}
 function $HashedCollection(){return globals.HashedCollection||(typeof HashedCollection=="undefined"?nil:HashedCollection)}
 return smalltalk.withContext(function($ctx1) { 
 var $3,$2,$4,$5,$6,$7,$8,$9,$10,$11,$12,$1;
-$3=_st($SmalltalkSettings())._at_ifAbsent_("helios.codeMirrorTheme",(function(){
-return smalltalk.withContext(function($ctx2) {
-return "default helios";
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-$ctx1.sendIdx["at:ifAbsent:"]=1;
+$3="helios.codeMirrorTheme"._settingValueIfAbsent_("default helios");
+$ctx1.sendIdx["settingValueIfAbsent:"]=1;
 $2="theme".__minus_gt($3);
 $ctx1.sendIdx["->"]=1;
 $4="mode".__minus_gt("text/x-stsrc");
@@ -417,18 +413,15 @@ $10="electricChars".__minus_gt(false);
 $ctx1.sendIdx["->"]=8;
 $11="keyMap".__minus_gt("Amber");
 $ctx1.sendIdx["->"]=9;
-$12="extraKeys".__minus_gt(_st($HashedCollection())._with_(_st(_st($SmalltalkSettings())._at_ifAbsent_("helios.completionKey",(function(){
-return smalltalk.withContext(function($ctx2) {
-return "Shift-Space";
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}))).__minus_gt("autocomplete")));
+$12="extraKeys".__minus_gt(_st($HashedCollection())._with_(_st("helios.completionKey"._settingValueIfAbsent_("Shift-Space")).__minus_gt("autocomplete")));
 $ctx1.sendIdx["->"]=10;
 $1=globals.HashedCollection._from_([$2,$4,$5,$6,$7,$8,$9,$10,$11,$12]);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"editorOptions",{},globals.HLCodeWidget)})},
 args: [],
-source: "editorOptions\x0a\x09^ #{\x0a\x09\x09'theme' -> (SmalltalkSettings at: 'helios.codeMirrorTheme' ifAbsent: [ 'default helios' ]).\x0a\x09\x09'mode' -> 'text/x-stsrc'.\x0a        'lineNumbers' -> true.\x0a        'enterMode' -> 'flat'.\x0a        'indentWithTabs' -> true.\x0a\x09\x09'indentUnit' -> 4.\x0a        'matchBrackets' -> true.\x0a        'electricChars' -> false.\x0a\x09\x09'keyMap' -> 'Amber'.\x0a\x09\x09'extraKeys' -> (HashedCollection with: (SmalltalkSettings at: 'helios.completionKey' ifAbsent: [ 'Shift-Space' ]) -> 'autocomplete')\x0a\x09}",
-messageSends: ["->", "at:ifAbsent:", "with:"],
-referencedClasses: ["SmalltalkSettings", "HashedCollection"]
+source: "editorOptions\x0a\x09^ #{\x0a\x09\x09'theme' -> ('helios.codeMirrorTheme' settingValueIfAbsent: 'default helios').\x0a\x09\x09'mode' -> 'text/x-stsrc'.\x0a        'lineNumbers' -> true.\x0a        'enterMode' -> 'flat'.\x0a        'indentWithTabs' -> true.\x0a\x09\x09'indentUnit' -> 4.\x0a        'matchBrackets' -> true.\x0a        'electricChars' -> false.\x0a\x09\x09'keyMap' -> 'Amber'.\x0a\x09\x09'extraKeys' -> (HashedCollection with: ('helios.completionKey' settingValueIfAbsent: 'Shift-Space') -> 'autocomplete')\x0a\x09}",
+messageSends: ["->", "settingValueIfAbsent:", "with:"],
+referencedClasses: ["HashedCollection"]
 }),
 globals.HLCodeWidget);
 

+ 2 - 2
js/IDE.js

@@ -946,7 +946,7 @@ fn: function (aTextarea){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self['@editor'] = CodeMirror.fromTextArea(aTextarea, {
-		theme: globals.SmalltalkSettings['ide.codeMirrorTheme'] || 'default',
+		theme: 'ide.codeMirrorTheme'._settingValueIfAbsent_('default'),
 		mode: 'text/x-stsrc',
 		lineNumbers: true,
 		enterMode: 'flat',
@@ -957,7 +957,7 @@ self['@editor'] = CodeMirror.fromTextArea(aTextarea, {
 	});
 return self}, function($ctx1) {$ctx1.fill(self,"setEditorOn:",{aTextarea:aTextarea},globals.SourceArea)})},
 args: ["aTextarea"],
-source: "setEditorOn: aTextarea\x0a\x09<self['@editor'] = CodeMirror.fromTextArea(aTextarea, {\x0a\x09\x09theme: globals.SmalltalkSettings['ide.codeMirrorTheme'] || 'default',\x0a\x09\x09mode: 'text/x-stsrc',\x0a\x09\x09lineNumbers: true,\x0a\x09\x09enterMode: 'flat',\x0a\x09\x09indentWithTabs: true,\x0a\x09\x09indentUnit: 4,\x0a\x09\x09matchBrackets: true,\x0a\x09\x09electricChars: false\x0a\x09})>",
+source: "setEditorOn: aTextarea\x0a\x09<self['@editor'] = CodeMirror.fromTextArea(aTextarea, {\x0a\x09\x09theme: 'ide.codeMirrorTheme'._settingValueIfAbsent_('default'),\x0a\x09\x09mode: 'text/x-stsrc',\x0a\x09\x09lineNumbers: true,\x0a\x09\x09enterMode: 'flat',\x0a\x09\x09indentWithTabs: true,\x0a\x09\x09indentUnit: 4,\x0a\x09\x09matchBrackets: true,\x0a\x09\x09electricChars: false\x0a\x09})>",
 messageSends: [],
 referencedClasses: []
 }),

+ 288 - 10
js/Kernel-Infrastructure.js

@@ -2340,6 +2340,170 @@ referencedClasses: []
 globals.Transcript.klass);
 
 
+smalltalk.addClass('Setting', globals.Object, ['key', 'value', 'defaultValue'], 'Kernel-Infrastructure');
+globals.Setting.comment="I represent a setting accessible via `Smalltalk settings`.\x0a\x0aYou can read the value by `value` and set it by `value:`.\x0a\x0aConstruct me by: `'key' asSetting` or `'key' asSettingIfAbsent: 'defaultValue'`.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "defaultValue",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+var $1;
+$1=self["@defaultValue"];
+return $1;
+},
+args: [],
+source: "defaultValue\x0a\x09^ defaultValue",
+messageSends: [],
+referencedClasses: []
+}),
+globals.Setting);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "defaultValue:",
+protocol: 'accessing',
+fn: function (anObject){
+var self=this;
+self["@defaultValue"]=anObject;
+return self},
+args: ["anObject"],
+source: "defaultValue: anObject\x0a\x09defaultValue := anObject",
+messageSends: [],
+referencedClasses: []
+}),
+globals.Setting);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initialize",
+protocol: 'initialization',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+globals.Setting.superclass.fn.prototype._initialize.apply(_st(self), []);
+self["@value"]=nil;
+return self}, function($ctx1) {$ctx1.fill(self,"initialize",{},globals.Setting)})},
+args: [],
+source: "initialize\x0a\x09super initialize.\x0a\x0a\x09value := nil",
+messageSends: ["initialize"],
+referencedClasses: []
+}),
+globals.Setting);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+var $1;
+$1=self["@key"];
+return $1;
+},
+args: [],
+source: "key\x0a\x09^ key",
+messageSends: [],
+referencedClasses: []
+}),
+globals.Setting);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key:",
+protocol: 'accessing',
+fn: function (anObject){
+var self=this;
+self["@key"]=anObject;
+return self},
+args: ["anObject"],
+source: "key: anObject\x0a\x09key := anObject",
+messageSends: [],
+referencedClasses: []
+}),
+globals.Setting);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "value",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+function $Smalltalk(){return globals.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st($Smalltalk())._settings())._at_ifAbsent_(self._key(),(function(){
+return smalltalk.withContext(function($ctx2) {
+return self._defaultValue();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"value",{},globals.Setting)})},
+args: [],
+source: "value\x0a\x09^ Smalltalk settings at: self key ifAbsent: [ self defaultValue ]",
+messageSends: ["at:ifAbsent:", "settings", "key", "defaultValue"],
+referencedClasses: ["Smalltalk"]
+}),
+globals.Setting);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "value:",
+protocol: 'accessing',
+fn: function (aString){
+var self=this;
+function $Smalltalk(){return globals.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st($Smalltalk())._settings())._at_put_(self._key(),aString);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"value:",{aString:aString},globals.Setting)})},
+args: ["aString"],
+source: "value: aString\x0a\x09^ Smalltalk settings at: self key put: aString",
+messageSends: ["at:put:", "settings", "key"],
+referencedClasses: ["Smalltalk"]
+}),
+globals.Setting);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "at:ifAbsent:",
+protocol: 'instance creation',
+fn: function (aString,anotherString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=globals.Setting.klass.superclass.fn.prototype._new.apply(_st(self), []);
+_st($2)._key_(aString);
+_st($2)._defaultValue_(anotherString);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{aString:aString,anotherString:anotherString},globals.Setting.klass)})},
+args: ["aString", "anotherString"],
+source: "at: aString ifAbsent: anotherString\x0a\x09^ super new\x0a\x09\x09key: aString;\x0a\x09\x09defaultValue: anotherString;\x0a\x09\x09yourself",
+messageSends: ["key:", "new", "defaultValue:", "yourself"],
+referencedClasses: []
+}),
+globals.Setting.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "new",
+protocol: 'instance creation',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._shouldNotImplement();
+return self}, function($ctx1) {$ctx1.fill(self,"new",{},globals.Setting.klass)})},
+args: [],
+source: "new\x0a\x09self shouldNotImplement",
+messageSends: ["shouldNotImplement"],
+referencedClasses: []
+}),
+globals.Setting.klass);
+
+
 smalltalk.addClass('SmalltalkImage', globals.Object, [], 'Kernel-Infrastructure');
 globals.SmalltalkImage.comment="I represent the Smalltalk system, wrapping\x0aoperations of variable `smalltalk` declared in `js/boot.js`.\x0a\x0a## API\x0a\x0aI have only one instance, accessed with global variable `Smalltalk`.\x0a\x0aThe `smalltalk` object holds all class and packages defined in the system.\x0a\x0a## Classes\x0a\x0aClasses can be accessed using the following methods:\x0a\x0a- `#classes` answers the full list of Smalltalk classes in the system\x0a- `#at:` answers a specific class or `nil`\x0a\x0a## Packages\x0a\x0aPackages can be accessed using the following methods:\x0a\x0a- `#packages` answers the full list of packages\x0a- `#packageAt:` answers a specific package or `nil`\x0a\x0a## Parsing\x0a\x0aThe `#parse:` method is used to parse Amber source code.\x0aIt requires the `Compiler` package and the `js/parser.js` parser file in order to work.";
 smalltalk.addMethod(
@@ -2589,16 +2753,15 @@ selector: "defaultAmdNamespace",
 protocol: 'accessing amd',
 fn: function (){
 var self=this;
-function $SmalltalkSettings(){return globals.SmalltalkSettings||(typeof SmalltalkSettings=="undefined"?nil:SmalltalkSettings)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st($SmalltalkSettings())._at_("vm.defaultAmdNamespace");
+$1="vm.defaultAmdNamespace"._settingValue();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"defaultAmdNamespace",{},globals.SmalltalkImage)})},
 args: [],
-source: "defaultAmdNamespace\x0a\x09^ SmalltalkSettings at: 'vm.defaultAmdNamespace'",
-messageSends: ["at:"],
-referencedClasses: ["SmalltalkSettings"]
+source: "defaultAmdNamespace\x0a\x09^ 'vm.defaultAmdNamespace' settingValue",
+messageSends: ["settingValue"],
+referencedClasses: []
 }),
 globals.SmalltalkImage);
 
@@ -2608,14 +2771,13 @@ selector: "defaultAmdNamespace:",
 protocol: 'accessing amd',
 fn: function (aString){
 var self=this;
-function $SmalltalkSettings(){return globals.SmalltalkSettings||(typeof SmalltalkSettings=="undefined"?nil:SmalltalkSettings)}
 return smalltalk.withContext(function($ctx1) { 
-_st($SmalltalkSettings())._at_put_("vm.defaultAmdNamespace",aString);
+"vm.defaultAmdNamespace"._settingValue_(aString);
 return self}, function($ctx1) {$ctx1.fill(self,"defaultAmdNamespace:",{aString:aString},globals.SmalltalkImage)})},
 args: ["aString"],
-source: "defaultAmdNamespace: aString\x0a\x09SmalltalkSettings at: 'vm.defaultAmdNamespace' put: aString",
-messageSends: ["at:put:"],
-referencedClasses: ["SmalltalkSettings"]
+source: "defaultAmdNamespace: aString\x0a\x09'vm.defaultAmdNamespace' settingValue: aString",
+messageSends: ["settingValue:"],
+referencedClasses: []
 }),
 globals.SmalltalkImage);
 
@@ -2985,6 +3147,22 @@ referencedClasses: []
 }),
 globals.SmalltalkImage);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "settings",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+function $SmalltalkSettings(){return globals.SmalltalkSettings||(typeof SmalltalkSettings=="undefined"?nil:SmalltalkSettings)}
+return $SmalltalkSettings();
+},
+args: [],
+source: "settings\x0a\x09^ SmalltalkSettings",
+messageSends: [],
+referencedClasses: ["SmalltalkSettings"]
+}),
+globals.SmalltalkImage);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "version",
@@ -3110,4 +3288,104 @@ referencedClasses: []
 }),
 globals.String);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "asSetting",
+protocol: '*Kernel-Infrastructure',
+fn: function (){
+var self=this;
+var parts;
+function $Setting(){return globals.Setting||(typeof Setting=="undefined"?nil:Setting)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3;
+parts=self._tokenize_("|");
+$1=_st(_st(parts)._size()).__eq((1));
+if(smalltalk.assert($1)){
+$2=_st($Setting())._at_ifAbsent_(self,nil);
+return $2;
+} else {
+$3=_st(_st(parts)._first())._asSettingIfAbsent_(_st(parts)._second());
+return $3;
+};
+return self}, function($ctx1) {$ctx1.fill(self,"asSetting",{parts:parts},globals.String)})},
+args: [],
+source: "asSetting\x0a\x09| parts |\x0a\x09parts := self tokenize: '|'.\x0a\x09parts size = 1\x0a\x09\x09ifTrue: [ ^ Setting at: self ifAbsent: nil ]\x0a\x09\x09ifFalse: [ ^ parts first asSettingIfAbsent: parts second ]",
+messageSends: ["tokenize:", "ifTrue:ifFalse:", "=", "size", "at:ifAbsent:", "asSettingIfAbsent:", "first", "second"],
+referencedClasses: ["Setting"]
+}),
+globals.String);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "asSettingIfAbsent:",
+protocol: '*Kernel-Infrastructure',
+fn: function (aString){
+var self=this;
+function $Setting(){return globals.Setting||(typeof Setting=="undefined"?nil:Setting)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st($Setting())._at_ifAbsent_(self,aString);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"asSettingIfAbsent:",{aString:aString},globals.String)})},
+args: ["aString"],
+source: "asSettingIfAbsent: aString\x0a\x09^ Setting at: self ifAbsent: aString",
+messageSends: ["at:ifAbsent:"],
+referencedClasses: ["Setting"]
+}),
+globals.String);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "settingValue",
+protocol: '*Kernel-Infrastructure',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self._asSetting())._value();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"settingValue",{},globals.String)})},
+args: [],
+source: "settingValue\x0a\x09^ self asSetting value",
+messageSends: ["value", "asSetting"],
+referencedClasses: []
+}),
+globals.String);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "settingValue:",
+protocol: '*Kernel-Infrastructure',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self._asSetting())._value_(aString);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"settingValue:",{aString:aString},globals.String)})},
+args: ["aString"],
+source: "settingValue: aString\x0a\x09^ self asSetting value: aString",
+messageSends: ["value:", "asSetting"],
+referencedClasses: []
+}),
+globals.String);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "settingValueIfAbsent:",
+protocol: '*Kernel-Infrastructure',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self._asSettingIfAbsent_(aString))._value();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"settingValueIfAbsent:",{aString:aString},globals.String)})},
+args: ["aString"],
+source: "settingValueIfAbsent: aString\x0a\x09^ (self asSettingIfAbsent: aString) value",
+messageSends: ["value", "asSettingIfAbsent:"],
+referencedClasses: []
+}),
+globals.String);
+
 });

+ 2 - 2
st/Helios-Workspace.st

@@ -82,7 +82,7 @@ currentLineOrSelection
 
 editorOptions
 	^ #{
-		'theme' -> (SmalltalkSettings at: 'helios.codeMirrorTheme' ifAbsent: [ 'default helios' ]).
+		'theme' -> ('helios.codeMirrorTheme' settingValueIfAbsent: 'default helios').
 		'mode' -> 'text/x-stsrc'.
         'lineNumbers' -> true.
         'enterMode' -> 'flat'.
@@ -91,7 +91,7 @@ editorOptions
         'matchBrackets' -> true.
         'electricChars' -> false.
 		'keyMap' -> 'Amber'.
-		'extraKeys' -> (HashedCollection with: (SmalltalkSettings at: 'helios.completionKey' ifAbsent: [ 'Shift-Space' ]) -> 'autocomplete')
+		'extraKeys' -> (HashedCollection with: ('helios.completionKey' settingValueIfAbsent: 'Shift-Space') -> 'autocomplete')
 	}
 !
 

+ 1 - 1
st/IDE.st

@@ -210,7 +210,7 @@ selection
 
 setEditorOn: aTextarea
 	<self['@editor'] = CodeMirror.fromTextArea(aTextarea, {
-		theme: globals.SmalltalkSettings['ide.codeMirrorTheme'] || 'default',
+		theme: 'ide.codeMirrorTheme'._settingValueIfAbsent_('default'),
 		mode: 'text/x-stsrc',
 		lineNumbers: true,
 		enterMode: 'flat',

+ 87 - 2
st/Kernel-Infrastructure.st

@@ -909,6 +909,63 @@ show: anObject
 	self current show: anObject
 ! !
 
+Object subclass: #Setting
+	instanceVariableNames: 'key value defaultValue'
+	package: 'Kernel-Infrastructure'!
+!Setting commentStamp!
+I represent a setting accessible via `Smalltalk settings`.
+
+You can read the value by `value` and set it by `value:`.
+
+Construct me by: `'key' asSetting` or `'key' asSettingIfAbsent: 'defaultValue'`.!
+
+!Setting methodsFor: 'accessing'!
+
+defaultValue
+	^ defaultValue
+!
+
+defaultValue: anObject
+	defaultValue := anObject
+!
+
+key
+	^ key
+!
+
+key: anObject
+	key := anObject
+!
+
+value
+	^ Smalltalk settings at: self key ifAbsent: [ self defaultValue ]
+!
+
+value: aString
+	^ Smalltalk settings at: self key put: aString
+! !
+
+!Setting methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+
+	value := nil
+! !
+
+!Setting class methodsFor: 'instance creation'!
+
+at: aString ifAbsent: anotherString
+	^ super new
+		key: aString;
+		defaultValue: anotherString;
+		yourself
+!
+
+new
+	self shouldNotImplement
+! !
+
 Object subclass: #SmalltalkImage
 	instanceVariableNames: ''
 	package: 'Kernel-Infrastructure'!
@@ -999,6 +1056,10 @@ reservedWords
 	<return smalltalk.reservedWords>
 !
 
+settings
+	^ SmalltalkSettings
+!
+
 version
 	"Answer the version string of Amber"
 	
@@ -1017,11 +1078,11 @@ amdRequire
 !
 
 defaultAmdNamespace
-	^ SmalltalkSettings at: 'vm.defaultAmdNamespace'
+	^ 'vm.defaultAmdNamespace' settingValue
 !
 
 defaultAmdNamespace: aString
-	SmalltalkSettings at: 'vm.defaultAmdNamespace' put: aString
+	'vm.defaultAmdNamespace' settingValue: aString
 ! !
 
 !SmalltalkImage methodsFor: 'classes'!
@@ -1198,5 +1259,29 @@ do: aBlock displayingProgress: aString
 asJavaScriptSelector
 	"Return first keyword of the selector, without trailing colon."
 	^ self replace: '^([a-zA-Z0-9]*).*$' with: '$1'
+!
+
+asSetting
+	| parts |
+	parts := self tokenize: '|'.
+	parts size = 1
+		ifTrue: [ ^ Setting at: self ifAbsent: nil ]
+		ifFalse: [ ^ parts first asSettingIfAbsent: parts second ]
+!
+
+asSettingIfAbsent: aString
+	^ Setting at: self ifAbsent: aString
+!
+
+settingValue
+	^ self asSetting value
+!
+
+settingValue: aString
+	^ self asSetting value: aString
+!
+
+settingValueIfAbsent: aString
+	^ (self asSettingIfAbsent: aString) value
 ! !