Jelajahi Sumber

AmberCli: new package combining FileServer and REPL in one tool

Manfred Kroehnert 11 tahun lalu
induk
melakukan
d286af6270
5 mengubah file dengan 20398 tambahan dan 0 penghapusan
  1. 19 0
      cli/index.html
  2. 765 0
      cli/js/AmberCli.deploy.js
  3. 966 0
      cli/js/AmberCli.js
  4. 17748 0
      cli/js/amber-cli.js
  5. 900 0
      cli/st/AmberCli.st

+ 19 - 0
cli/index.html

@@ -0,0 +1,19 @@
+<!DOCTYPE html> 
+<html> 
+
+  <head> 
+    <title>Amber Smalltalk</title> 
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
+    <meta name="author" content="Nicolas Petton" /> 
+    <script type='text/javascript' src='../js/amber.js'></script> 
+  </head> 
+
+  <body> 
+    <script type='text/javascript'>
+      loadAmber({
+        files: ['AmberCli.js'],
+        prefix: 'cli/js',
+        ready: function() {smalltalk.Browser._open()}})
+    </script> 
+  </body> 
+</html> 

File diff ditekan karena terlalu besar
+ 765 - 0
cli/js/AmberCli.deploy.js


File diff ditekan karena terlalu besar
+ 966 - 0
cli/js/AmberCli.js


File diff ditekan karena terlalu besar
+ 17748 - 0
cli/js/amber-cli.js


+ 900 - 0
cli/st/AmberCli.st

@@ -0,0 +1,900 @@
+Smalltalk current createPackage: 'AmberCli'!
+Object subclass: #AmberCli
+	instanceVariableNames: ''
+	package: 'AmberCli'!
+
+!AmberCli class methodsFor: 'commandline'!
+
+commandLineSwitches
+	"Collect all methodnames from the 'commands' protocol of the class
+	 and select the ones with only one parameter.
+	 Then remove the ':' at the end of the name.
+	 Additionally all uppercase letters are made lowercase and preceded by a '-'.
+	 Example: fallbackPage: becomes --fallback-page.
+	 Return the Array containing the commandline switches."
+	| switches |
+	switches := ((self class methodsInProtocol: 'commands') collect: [ :each | each selector]).
+	switches := switches select: [ :each | each match: '^[^:]*:$'].
+	switches :=switches collect: [ :each |
+		(each allButLast replace: '([A-Z])' with: '-$1') asLowercase].
+	^switches
+!
+
+handleArguments: args
+	| command |
+	command := self selectorForCommandLineSwitch: (args first).
+	args remove: args first.
+	self perform: command  withArguments: (Array with: args).
+!
+
+selectorForCommandLineSwitch: aSwitch
+	"Add ':' at the end
+	 and replace all occurences of a lowercase letter preceded by a '-' with
+	 the Uppercase letter.
+	 Example: fallback-page becomes fallbackPage:"
+	^(aSwitch replace: '-[a-z]' with: [ :each | each second asUppercase ]), ':'
+! !
+
+!AmberCli class methodsFor: 'commands'!
+
+help: args
+	console log: 'Available Commands:'.
+	self commandLineSwitches do: [ :each | console log: each ]
+!
+
+repl: args
+	^Repl new createInterface
+!
+
+server: args
+	^(FileServer createServerWithArguments: args) start
+! !
+
+!AmberCli class methodsFor: 'startup'!
+
+main
+	"Main entry point for Amber applications.
+	Parses commandline arguments and starts the according subprogram."
+	| args |
+	args := process argv.
+	"Remove the first args which contain the path to the node executable and the script file."
+	args removeFrom: 1 to: 3.
+	
+	(args isEmpty)
+		ifTrue: [self help: nil]
+		ifFalse: [^self handleArguments: args]
+! !
+
+Object subclass: #FileServer
+	instanceVariableNames: 'path http fs url host port basePath util username password fallbackPage'
+	package: 'AmberCli'!
+
+!FileServer methodsFor: 'accessing'!
+
+basePath
+	^basePath ifNil: ['./']
+!
+
+basePath: aString
+	basePath := aString
+!
+
+fallbackPage
+	^fallbackPage
+!
+
+fallbackPage: aString
+	fallbackPage := aString
+!
+
+host
+	^host
+!
+
+host: hostname
+	host := hostname
+!
+
+password: aPassword
+	password := aPassword.
+!
+
+port
+	^port
+!
+
+port: aNumber
+	port := aNumber
+!
+
+username: aUsername
+	username := aUsername.
+!
+
+username: aUsername password: aPassword
+	username := aUsername.
+	password := aPassword.
+! !
+
+!FileServer methodsFor: 'initialization'!
+
+checkDirectoryLayout
+	(fs existsSync: self basePath, 'index.html') ifFalse: [
+		console warn: 'Warning: project directory does not contain index.html'].
+	(fs existsSync: self basePath, 'st') ifFalse: [
+		console warn: 'Warning: project directory is missing an "st" directory'].
+	(fs existsSync: self basePath, 'js') ifFalse: [
+		console warn: 'Warning: project directory is missing a "js" directory'].
+!
+
+initialize
+	super initialize.
+	path := self require: 'path'.
+	http := self require: 'http'.
+	fs := self require: 'fs'.
+	util := self require: 'util'.
+	url := self require: 'url'.
+	host := self class defaultHost.
+	port := self class defaultPort.
+	username := nil.
+	password := nil.
+	fallbackPage := nil.
+! !
+
+!FileServer methodsFor: 'private'!
+
+base64Decode: aString
+	<return (new Buffer(aString, 'base64').toString())>
+!
+
+isAuthenticated: aRequest
+	"Basic HTTP Auth: http://stackoverflow.com/a/5957629/293175
+	 and https://gist.github.com/1686663"
+	| header token auth parts|
+
+	(username isNil and: [password isNil]) ifTrue: [^true].
+
+	"get authentication header"
+	header := (aRequest headers at: 'authorization') ifNil:[''].
+	(header isEmpty)
+	ifTrue: [^false]
+	ifFalse: [
+		"get authentication token"
+		token := (header tokenize: ' ') ifNil:[''].
+		"convert back from base64"
+		auth := self base64Decode: (token at: 2).
+		"split token at colon"
+		parts := auth tokenize: ':'.
+
+		((username = (parts at: 1)) and: [password = (parts at: 2)])
+			ifTrue: [^true]
+			ifFalse: [^false]
+	].
+!
+
+require: aModuleString
+	"call to the require function"
+	^require value: aModuleString
+!
+
+writeData: data toFileNamed: aFilename
+	console log: aFilename
+! !
+
+!FileServer methodsFor: 'request handling'!
+
+handleGETRequest: aRequest respondTo: aResponse
+	| uri filename |
+	uri := (url parse: aRequest url) pathname.
+	filename := path join: self basePath with: uri.
+	fs exists: filename do: [:aBoolean |
+		aBoolean
+			ifFalse: [self respondNotFoundTo: aResponse]
+			ifTrue: [self respondFileNamed: filename to: aResponse]]
+!
+
+handleOPTIONSRequest: aRequest respondTo: aResponse
+	aResponse writeHead: 200 options: #{'Access-Control-Allow-Origin' -> '*'.
+					'Access-Control-Allow-Methods' -> 'GET, PUT, POST, DELETE, OPTIONS'.
+					'Access-Control-Allow-Headers' -> 'Content-Type, Accept'.
+					'Content-Length' -> 0.
+					'Access-Control-Max-Age' -> 10}.
+	aResponse end
+!
+
+handlePUTRequest: aRequest respondTo: aResponse
+	| file stream |
+	(self isAuthenticated: aRequest)
+		ifFalse: [self respondAuthenticationRequiredTo: aResponse. ^nil].
+
+	file := '.', aRequest url.
+	stream := fs createWriteStream: file.
+
+	stream on: 'error' do: [:error |
+		console warn: 'Error creating WriteStream for file ', file.
+		console warn: '    Did you forget to create the necessary js/ or st/ directory in your project?'.
+		console warn: '    The exact error is: ', error.
+		self respondNotCreatedTo: aResponse].
+
+	stream on: 'close' do: [
+		self respondCreatedTo: aResponse].
+
+	aRequest setEncoding: 'utf8'.
+	aRequest on: 'data' do: [:data |
+		stream write: data].
+
+	aRequest on: 'end' do: [
+		stream writable ifTrue: [stream end]]
+!
+
+handleRequest: aRequest respondTo: aResponse
+	aRequest method = 'PUT'
+		ifTrue: [self handlePUTRequest: aRequest respondTo: aResponse].
+	aRequest method = 'GET'
+		ifTrue:[self handleGETRequest: aRequest respondTo: aResponse].
+	aRequest method = 'OPTIONS'
+		ifTrue:[self handleOPTIONSRequest: aRequest respondTo: aResponse]
+!
+
+respondAuthenticationRequiredTo: aResponse
+	aResponse
+		writeHead: 401 options: #{'WWW-Authenticate' -> 'Basic realm="Secured Developer Area"'};
+		write: '<html><body>Authentication needed</body></html>';
+		end.
+!
+
+respondCreatedTo: aResponse
+	aResponse
+		writeHead: 201 options: #{'Content-Type' -> 'text/plain'. 'Access-Control-Allow-Origin' -> '*'};
+		end.
+!
+
+respondFileNamed: aFilename to: aResponse
+	| type filename |
+
+	filename := aFilename.
+	(fs statSync: aFilename) isDirectory ifTrue: [
+		filename := filename, 'index.html'].
+
+	fs readFile: filename do: [:ex :file |
+		ex notNil 
+			ifTrue: [
+				console log: filename, ' does not exist'.
+				self respondInternalErrorTo: aResponse]
+			ifFalse: [
+				type := self class mimeTypeFor: filename.
+				type = 'application/javascript'
+					ifTrue: [ type:=type,';charset=utf-8' ].
+				aResponse 
+					writeHead: 200 options:  #{'Content-Type' -> type};
+					write: file encoding: 'binary';
+					end]]
+!
+
+respondInternalErrorTo: aResponse
+	aResponse 
+		writeHead: 500 options: #{'Content-Type' -> 'text/plain'};
+		write: '500 Internal server error';
+		end
+!
+
+respondNotCreatedTo: aResponse
+	aResponse
+		writeHead: 400 options: #{'Content-Type' -> 'text/plain'};
+		write: 'File could not be created. Did you forget to create the st/js directories on the server?';
+		end.
+!
+
+respondNotFoundTo: aResponse
+	self fallbackPage isNil ifFalse: [^self respondFileNamed: self fallbackPage to: aResponse].
+	aResponse 
+		writeHead: 404 options: #{'Content-Type' -> 'text/plain'};
+		write: '404 Not found';
+		end
+!
+
+respondOKTo: aResponse
+	aResponse
+		writeHead: 200 options: #{'Content-Type' -> 'text/plain'. 'Access-Control-Allow-Origin' -> '*'};
+		end.
+! !
+
+!FileServer methodsFor: 'starting'!
+
+start
+	"Checks if required directory layout is present (issue warning if not).
+	 Afterwards start the server."
+	self checkDirectoryLayout.
+	(http createServer: [:request :response |
+	      self handleRequest: request respondTo: response])
+	      on: 'error' do: [:error | console log: 'Error starting server: ', error];
+	      on: 'listening' do: [console log: 'Starting file server on ', self host, ':', self port asString];
+	      listen: self port host: self host.
+!
+
+startOn: aPort
+	self port: aPort.
+	self start
+! !
+
+FileServer class instanceVariableNames: 'mimeTypes'!
+
+!FileServer class methodsFor: 'accessing'!
+
+commandLineSwitches
+	"Collect all methodnames from the 'accessing' protocol
+	 and select the ones with only one parameter.
+	 Then remove the ':' at the end of the name
+	 and add a '--' at the beginning.
+	 Additionally all uppercase letters are made lowercase and preceded by a '-'.
+	 Example: fallbackPage: becomes --fallback-page.
+	 Return the Array containing the commandline switches."
+	| switches |
+	switches := ((self methodsInProtocol: 'accessing') collect: [ :each | each selector]).
+	switches := switches select: [ :each | each match: '^[^:]*:$'].
+	switches :=switches collect: [ :each |
+		(each allButLast replace: '([A-Z])' with: '-$1') asLowercase replace: '^([a-z])' with: '--$1' ].
+	^switches
+!
+
+defaultHost
+	^'127.0.0.1'
+!
+
+defaultMimeTypes
+	^ #{
+		'%' -> 'application/x-trash'.
+		'323' -> 'text/h323'.
+		'abw' -> 'application/x-abiword'.
+		'ai' -> 'application/postscript'.
+		'aif' -> 'audio/x-aiff'.
+		'aifc' -> 'audio/x-aiff'.
+		'aiff' -> 'audio/x-aiff'.
+		'alc' -> 'chemical/x-alchemy'.
+		'art' -> 'image/x-jg'.
+		'asc' -> 'text/plain'.
+		'asf' -> 'video/x-ms-asf'.
+		'asn' -> 'chemical/x-ncbi-asn1-spec'.
+		'aso' -> 'chemical/x-ncbi-asn1-binary'.
+		'asx' -> 'video/x-ms-asf'.
+		'au' -> 'audio/basic'.
+		'avi' -> 'video/x-msvideo'.
+		'b' -> 'chemical/x-molconn-Z'.
+		'bak' -> 'application/x-trash'.
+		'bat' -> 'application/x-msdos-program'.
+		'bcpio' -> 'application/x-bcpio'.
+		'bib' -> 'text/x-bibtex'.
+		'bin' -> 'application/octet-stream'.
+		'bmp' -> 'image/x-ms-bmp'.
+		'book' -> 'application/x-maker'.
+		'bsd' -> 'chemical/x-crossfire'.
+		'c' -> 'text/x-csrc'.
+		'c++' -> 'text/x-c++src'.
+		'c3d' -> 'chemical/x-chem3d'.
+		'cac' -> 'chemical/x-cache'.
+		'cache' -> 'chemical/x-cache'.
+		'cascii' -> 'chemical/x-cactvs-binary'.
+		'cat' -> 'application/vnd.ms-pki.seccat'.
+		'cbin' -> 'chemical/x-cactvs-binary'.
+		'cc' -> 'text/x-c++src'.
+		'cdf' -> 'application/x-cdf'.
+		'cdr' -> 'image/x-coreldraw'.
+		'cdt' -> 'image/x-coreldrawtemplate'.
+		'cdx' -> 'chemical/x-cdx'.
+		'cdy' -> 'application/vnd.cinderella'.
+		'cef' -> 'chemical/x-cxf'.
+		'cer' -> 'chemical/x-cerius'.
+		'chm' -> 'chemical/x-chemdraw'.
+		'chrt' -> 'application/x-kchart'.
+		'cif' -> 'chemical/x-cif'.
+		'class' -> 'application/java-vm'.
+		'cls' -> 'text/x-tex'.
+		'cmdf' -> 'chemical/x-cmdf'.
+		'cml' -> 'chemical/x-cml'.
+		'cod' -> 'application/vnd.rim.cod'.
+		'com' -> 'application/x-msdos-program'.
+		'cpa' -> 'chemical/x-compass'.
+		'cpio' -> 'application/x-cpio'.
+		'cpp' -> 'text/x-c++src'.
+		'cpt' -> 'image/x-corelphotopaint'.
+		'crl' -> 'application/x-pkcs7-crl'.
+		'crt' -> 'application/x-x509-ca-cert'.
+		'csf' -> 'chemical/x-cache-csf'.
+		'csh' -> 'text/x-csh'.
+		'csm' -> 'chemical/x-csml'.
+		'csml' -> 'chemical/x-csml'.
+		'css' -> 'text/css'.
+		'csv' -> 'text/comma-separated-values'.
+		'ctab' -> 'chemical/x-cactvs-binary'.
+		'ctx' -> 'chemical/x-ctx'.
+		'cu' -> 'application/cu-seeme'.
+		'cub' -> 'chemical/x-gaussian-cube'.
+		'cxf' -> 'chemical/x-cxf'.
+		'cxx' -> 'text/x-c++src'.
+		'dat' -> 'chemical/x-mopac-input'.
+		'dcr' -> 'application/x-director'.
+		'deb' -> 'application/x-debian-package'.
+		'dif' -> 'video/dv'.
+		'diff' -> 'text/plain'.
+		'dir' -> 'application/x-director'.
+		'djv' -> 'image/vnd.djvu'.
+		'djvu' -> 'image/vnd.djvu'.
+		'dl' -> 'video/dl'.
+		'dll' -> 'application/x-msdos-program'.
+		'dmg' -> 'application/x-apple-diskimage'.
+		'dms' -> 'application/x-dms'.
+		'doc' -> 'application/msword'.
+		'dot' -> 'application/msword'.
+		'dv' -> 'video/dv'.
+		'dvi' -> 'application/x-dvi'.
+		'dx' -> 'chemical/x-jcamp-dx'.
+		'dxr' -> 'application/x-director'.
+		'emb' -> 'chemical/x-embl-dl-nucleotide'.
+		'embl' -> 'chemical/x-embl-dl-nucleotide'.
+		'ent' -> 'chemical/x-pdb'.
+		'eps' -> 'application/postscript'.
+		'etx' -> 'text/x-setext'.
+		'exe' -> 'application/x-msdos-program'.
+		'ez' -> 'application/andrew-inset'.
+		'fb' -> 'application/x-maker'.
+		'fbdoc' -> 'application/x-maker'.
+		'fch' -> 'chemical/x-gaussian-checkpoint'.
+		'fchk' -> 'chemical/x-gaussian-checkpoint'.
+		'fig' -> 'application/x-xfig'.
+		'flac' -> 'application/x-flac'.
+		'fli' -> 'video/fli'.
+		'fm' -> 'application/x-maker'.
+		'frame' -> 'application/x-maker'.
+		'frm' -> 'application/x-maker'.
+		'gal' -> 'chemical/x-gaussian-log'.
+		'gam' -> 'chemical/x-gamess-input'.
+		'gamin' -> 'chemical/x-gamess-input'.
+		'gau' -> 'chemical/x-gaussian-input'.
+		'gcd' -> 'text/x-pcs-gcd'.
+		'gcf' -> 'application/x-graphing-calculator'.
+		'gcg' -> 'chemical/x-gcg8-sequence'.
+		'gen' -> 'chemical/x-genbank'.
+		'gf' -> 'application/x-tex-gf'.
+		'gif' -> 'image/gif'.
+		'gjc' -> 'chemical/x-gaussian-input'.
+		'gjf' -> 'chemical/x-gaussian-input'.
+		'gl' -> 'video/gl'.
+		'gnumeric' -> 'application/x-gnumeric'.
+		'gpt' -> 'chemical/x-mopac-graph'.
+		'gsf' -> 'application/x-font'.
+		'gsm' -> 'audio/x-gsm'.
+		'gtar' -> 'application/x-gtar'.
+		'h' -> 'text/x-chdr'.
+		'h++' -> 'text/x-c++hdr'.
+		'hdf' -> 'application/x-hdf'.
+		'hh' -> 'text/x-c++hdr'.
+		'hin' -> 'chemical/x-hin'.
+		'hpp' -> 'text/x-c++hdr'.
+		'hqx' -> 'application/mac-binhex40'.
+		'hs' -> 'text/x-haskell'.
+		'hta' -> 'application/hta'.
+		'htc' -> 'text/x-component'.
+		'htm' -> 'text/html'.
+		'html' -> 'text/html'.
+		'hxx' -> 'text/x-c++hdr'.
+		'ica' -> 'application/x-ica'.
+		'ice' -> 'x-conference/x-cooltalk'.
+		'ico' -> 'image/x-icon'.
+		'ics' -> 'text/calendar'.
+		'icz' -> 'text/calendar'.
+		'ief' -> 'image/ief'.
+		'iges' -> 'model/iges'.
+		'igs' -> 'model/iges'.
+		'iii' -> 'application/x-iphone'.
+		'inp' -> 'chemical/x-gamess-input'.
+		'ins' -> 'application/x-internet-signup'.
+		'iso' -> 'application/x-iso9660-image'.
+		'isp' -> 'application/x-internet-signup'.
+		'ist' -> 'chemical/x-isostar'.
+		'istr' -> 'chemical/x-isostar'.
+		'jad' -> 'text/vnd.sun.j2me.app-descriptor'.
+		'jar' -> 'application/java-archive'.
+		'java' -> 'text/x-java'.
+		'jdx' -> 'chemical/x-jcamp-dx'.
+		'jmz' -> 'application/x-jmol'.
+		'jng' -> 'image/x-jng'.
+		'jnlp' -> 'application/x-java-jnlp-file'.
+		'jpe' -> 'image/jpeg'.
+		'jpeg' -> 'image/jpeg'.
+		'jpg' -> 'image/jpeg'.
+		'js' -> 'application/javascript'.
+		'kar' -> 'audio/midi'.
+		'key' -> 'application/pgp-keys'.
+		'kil' -> 'application/x-killustrator'.
+		'kin' -> 'chemical/x-kinemage'.
+		'kpr' -> 'application/x-kpresenter'.
+		'kpt' -> 'application/x-kpresenter'.
+		'ksp' -> 'application/x-kspread'.
+		'kwd' -> 'application/x-kword'.
+		'kwt' -> 'application/x-kword'.
+		'latex' -> 'application/x-latex'.
+		'lha' -> 'application/x-lha'.
+		'lhs' -> 'text/x-literate-haskell'.
+		'lsf' -> 'video/x-la-asf'.
+		'lsx' -> 'video/x-la-asf'.
+		'ltx' -> 'text/x-tex'.
+		'lzh' -> 'application/x-lzh'.
+		'lzx' -> 'application/x-lzx'.
+		'm3u' -> 'audio/x-mpegurl'.
+		'm4a' -> 'audio/mpeg'.
+		'maker' -> 'application/x-maker'.
+		'man' -> 'application/x-troff-man'.
+		'mcif' -> 'chemical/x-mmcif'.
+		'mcm' -> 'chemical/x-macmolecule'.
+		'mdb' -> 'application/msaccess'.
+		'me' -> 'application/x-troff-me'.
+		'mesh' -> 'model/mesh'.
+		'mid' -> 'audio/midi'.
+		'midi' -> 'audio/midi'.
+		'mif' -> 'application/x-mif'.
+		'mm' -> 'application/x-freemind'.
+		'mmd' -> 'chemical/x-macromodel-input'.
+		'mmf' -> 'application/vnd.smaf'.
+		'mml' -> 'text/mathml'.
+		'mmod' -> 'chemical/x-macromodel-input'.
+		'mng' -> 'video/x-mng'.
+		'moc' -> 'text/x-moc'.
+		'mol' -> 'chemical/x-mdl-molfile'.
+		'mol2' -> 'chemical/x-mol2'.
+		'moo' -> 'chemical/x-mopac-out'.
+		'mop' -> 'chemical/x-mopac-input'.
+		'mopcrt' -> 'chemical/x-mopac-input'.
+		'mov' -> 'video/quicktime'.
+		'movie' -> 'video/x-sgi-movie'.
+		'mp2' -> 'audio/mpeg'.
+		'mp3' -> 'audio/mpeg'.
+		'mp4' -> 'video/mp4'.
+		'mpc' -> 'chemical/x-mopac-input'.
+		'mpe' -> 'video/mpeg'.
+		'mpeg' -> 'video/mpeg'.
+		'mpega' -> 'audio/mpeg'.
+		'mpg' -> 'video/mpeg'.
+		'mpga' -> 'audio/mpeg'.
+		'ms' -> 'application/x-troff-ms'.
+		'msh' -> 'model/mesh'.
+		'msi' -> 'application/x-msi'.
+		'mvb' -> 'chemical/x-mopac-vib'.
+		'mxu' -> 'video/vnd.mpegurl'.
+		'nb' -> 'application/mathematica'.
+		'nc' -> 'application/x-netcdf'.
+		'nwc' -> 'application/x-nwc'.
+		'o' -> 'application/x-object'.
+		'oda' -> 'application/oda'.
+		'odb' -> 'application/vnd.oasis.opendocument.database'.
+		'odc' -> 'application/vnd.oasis.opendocument.chart'.
+		'odf' -> 'application/vnd.oasis.opendocument.formula'.
+		'odg' -> 'application/vnd.oasis.opendocument.graphics'.
+		'odi' -> 'application/vnd.oasis.opendocument.image'.
+		'odm' -> 'application/vnd.oasis.opendocument.text-master'.
+		'odp' -> 'application/vnd.oasis.opendocument.presentation'.
+		'ods' -> 'application/vnd.oasis.opendocument.spreadsheet'.
+		'odt' -> 'application/vnd.oasis.opendocument.text'.
+		'ogg' -> 'application/ogg'.
+		'old' -> 'application/x-trash'.
+		'oth' -> 'application/vnd.oasis.opendocument.text-web'.
+		'oza' -> 'application/x-oz-application'.
+		'p' -> 'text/x-pascal'.
+		'p7r' -> 'application/x-pkcs7-certreqresp'.
+		'pac' -> 'application/x-ns-proxy-autoconfig'.
+		'pas' -> 'text/x-pascal'.
+		'pat' -> 'image/x-coreldrawpattern'.
+		'pbm' -> 'image/x-portable-bitmap'.
+		'pcf' -> 'application/x-font'.
+		'pcf.Z' -> 'application/x-font'.
+		'pcx' -> 'image/pcx'.
+		'pdb' -> 'chemical/x-pdb'.
+		'pdf' -> 'application/pdf'.
+		'pfa' -> 'application/x-font'.
+		'pfb' -> 'application/x-font'.
+		'pgm' -> 'image/x-portable-graymap'.
+		'pgn' -> 'application/x-chess-pgn'.
+		'pgp' -> 'application/pgp-signature'.
+		'pk' -> 'application/x-tex-pk'.
+		'pl' -> 'text/x-perl'.
+		'pls' -> 'audio/x-scpls'.
+		'pm' -> 'text/x-perl'.
+		'png' -> 'image/png'.
+		'pnm' -> 'image/x-portable-anymap'.
+		'pot' -> 'text/plain'.
+		'ppm' -> 'image/x-portable-pixmap'.
+		'pps' -> 'application/vnd.ms-powerpoint'.
+		'ppt' -> 'application/vnd.ms-powerpoint'.
+		'prf' -> 'application/pics-rules'.
+		'prt' -> 'chemical/x-ncbi-asn1-ascii'.
+		'ps' -> 'application/postscript'.
+		'psd' -> 'image/x-photoshop'.
+		'psp' -> 'text/x-psp'.
+		'py' -> 'text/x-python'.
+		'pyc' -> 'application/x-python-code'.
+		'pyo' -> 'application/x-python-code'.
+		'qt' -> 'video/quicktime'.
+		'qtl' -> 'application/x-quicktimeplayer'.
+		'ra' -> 'audio/x-realaudio'.
+		'ram' -> 'audio/x-pn-realaudio'.
+		'rar' -> 'application/rar'.
+		'ras' -> 'image/x-cmu-raster'.
+		'rd' -> 'chemical/x-mdl-rdfile'.
+		'rdf' -> 'application/rdf+xml'.
+		'rgb' -> 'image/x-rgb'.
+		'rm' -> 'audio/x-pn-realaudio'.
+		'roff' -> 'application/x-troff'.
+		'ros' -> 'chemical/x-rosdal'.
+		'rpm' -> 'application/x-redhat-package-manager'.
+		'rss' -> 'application/rss+xml'.
+		'rtf' -> 'text/rtf'.
+		'rtx' -> 'text/richtext'.
+		'rxn' -> 'chemical/x-mdl-rxnfile'.
+		'sct' -> 'text/scriptlet'.
+		'sd' -> 'chemical/x-mdl-sdfile'.
+		'sd2' -> 'audio/x-sd2'.
+		'sda' -> 'application/vnd.stardivision.draw'.
+		'sdc' -> 'application/vnd.stardivision.calc'.
+		'sdd' -> 'application/vnd.stardivision.impress'.
+		'sdf' -> 'chemical/x-mdl-sdfile'.
+		'sdp' -> 'application/vnd.stardivision.impress'.
+		'sdw' -> 'application/vnd.stardivision.writer'.
+		'ser' -> 'application/java-serialized-object'.
+		'sgf' -> 'application/x-go-sgf'.
+		'sgl' -> 'application/vnd.stardivision.writer-global'.
+		'sh' -> 'text/x-sh'.
+		'shar' -> 'application/x-shar'.
+		'shtml' -> 'text/html'.
+		'sid' -> 'audio/prs.sid'.
+		'sik' -> 'application/x-trash'.
+		'silo' -> 'model/mesh'.
+		'sis' -> 'application/vnd.symbian.install'.
+		'sit' -> 'application/x-stuffit'.
+		'skd' -> 'application/x-koan'.
+		'skm' -> 'application/x-koan'.
+		'skp' -> 'application/x-koan'.
+		'skt' -> 'application/x-koan'.
+		'smf' -> 'application/vnd.stardivision.math'.
+		'smi' -> 'application/smil'.
+		'smil' -> 'application/smil'.
+		'snd' -> 'audio/basic'.
+		'spc' -> 'chemical/x-galactic-spc'.
+		'spl' -> 'application/x-futuresplash'.
+		'src' -> 'application/x-wais-source'.
+		'stc' -> 'application/vnd.sun.xml.calc.template'.
+		'std' -> 'application/vnd.sun.xml.draw.template'.
+		'sti' -> 'application/vnd.sun.xml.impress.template'.
+		'stl' -> 'application/vnd.ms-pki.stl'.
+		'stw' -> 'application/vnd.sun.xml.writer.template'.
+		'sty' -> 'text/x-tex'.
+		'sv4cpio' -> 'application/x-sv4cpio'.
+		'sv4crc' -> 'application/x-sv4crc'.
+		'svg' -> 'image/svg+xml'.
+		'svgz' -> 'image/svg+xml'.
+		'sw' -> 'chemical/x-swissprot'.
+		'swf' -> 'application/x-shockwave-flash'.
+		'swfl' -> 'application/x-shockwave-flash'.
+		'sxc' -> 'application/vnd.sun.xml.calc'.
+		'sxd' -> 'application/vnd.sun.xml.draw'.
+		'sxg' -> 'application/vnd.sun.xml.writer.global'.
+		'sxi' -> 'application/vnd.sun.xml.impress'.
+		'sxm' -> 'application/vnd.sun.xml.math'.
+		'sxw' -> 'application/vnd.sun.xml.writer'.
+		't' -> 'application/x-troff'.
+		'tar' -> 'application/x-tar'.
+		'taz' -> 'application/x-gtar'.
+		'tcl' -> 'text/x-tcl'.
+		'tex' -> 'text/x-tex'.
+		'texi' -> 'application/x-texinfo'.
+		'texinfo' -> 'application/x-texinfo'.
+		'text' -> 'text/plain'.
+		'tgf' -> 'chemical/x-mdl-tgf'.
+		'tgz' -> 'application/x-gtar'.
+		'tif' -> 'image/tiff'.
+		'tiff' -> 'image/tiff'.
+		'tk' -> 'text/x-tcl'.
+		'tm' -> 'text/texmacs'.
+		'torrent' -> 'application/x-bittorrent'.
+		'tr' -> 'application/x-troff'.
+		'ts' -> 'text/texmacs'.
+		'tsp' -> 'application/dsptype'.
+		'tsv' -> 'text/tab-separated-values'.
+		'txt' -> 'text/plain'.
+		'udeb' -> 'application/x-debian-package'.
+		'uls' -> 'text/iuls'.
+		'ustar' -> 'application/x-ustar'.
+		'val' -> 'chemical/x-ncbi-asn1-binary'.
+		'vcd' -> 'application/x-cdlink'.
+		'vcf' -> 'text/x-vcard'.
+		'vcs' -> 'text/x-vcalendar'.
+		'vmd' -> 'chemical/x-vmd'.
+		'vms' -> 'chemical/x-vamas-iso14976'.
+		'vor' -> 'application/vnd.stardivision.writer'.
+		'vrm' -> 'x-world/x-vrml'.
+		'vrml' -> 'x-world/x-vrml'.
+		'vsd' -> 'application/vnd.visio'.
+		'wad' -> 'application/x-doom'.
+		'wav' -> 'audio/x-wav'.
+		'wax' -> 'audio/x-ms-wax'.
+		'wbmp' -> 'image/vnd.wap.wbmp'.
+		'wbxml' -> 'application/vnd.wap.wbxml'.
+		'wk' -> 'application/x-123'.
+		'wm' -> 'video/x-ms-wm'.
+		'wma' -> 'audio/x-ms-wma'.
+		'wmd' -> 'application/x-ms-wmd'.
+		'wml' -> 'text/vnd.wap.wml'.
+		'wmlc' -> 'application/vnd.wap.wmlc'.
+		'wmls' -> 'text/vnd.wap.wmlscript'.
+		'wmlsc' -> 'application/vnd.wap.wmlscriptc'.
+		'wmv' -> 'video/x-ms-wmv'.
+		'wmx' -> 'video/x-ms-wmx'.
+		'wmz' -> 'application/x-ms-wmz'.
+		'wp5' -> 'application/wordperfect5.1'.
+		'wpd' -> 'application/wordperfect'.
+		'wrl' -> 'x-world/x-vrml'.
+		'wsc' -> 'text/scriptlet'.
+		'wvx' -> 'video/x-ms-wvx'.
+		'wz' -> 'application/x-wingz'.
+		'xbm' -> 'image/x-xbitmap'.
+		'xcf' -> 'application/x-xcf'.
+		'xht' -> 'application/xhtml+xml'.
+		'xhtml' -> 'application/xhtml+xml'.
+		'xlb' -> 'application/vnd.ms-excel'.
+		'xls' -> 'application/vnd.ms-excel'.
+		'xlt' -> 'application/vnd.ms-excel'.
+		'xml' -> 'application/xml'.
+		'xpi' -> 'application/x-xpinstall'.
+		'xpm' -> 'image/x-xpixmap'.
+		'xsl' -> 'application/xml'.
+		'xtel' -> 'chemical/x-xtel'.
+		'xul' -> 'application/vnd.mozilla.xul+xml'.
+		'xwd' -> 'image/x-xwindowdump'.
+		'xyz' -> 'chemical/x-xyz'.
+		'zip' -> 'application/zip'.
+		'zmt' -> 'chemical/x-mopac-input'.
+		'~' -> 'application/x-trash'
+	}
+!
+
+defaultPort
+	^4000
+!
+
+mimeTypeFor: aString
+	^self mimeTypes at: (aString replace: '.*[\.]' with: '') ifAbsent: ['text/plain']
+!
+
+mimeTypes
+	^mimeTypes ifNil: [mimeTypes := self defaultMimeTypes]
+!
+
+printHelp
+	console log: 'Available commandline options are:'.
+	console log: '--help'.
+	self commandLineSwitches do: [ :each |
+		console log: each, ' <parameter>']
+!
+
+selectorForCommandLineSwitch: aSwitch
+	"Remove the trailing '--', add ':' at the end
+	 and replace all occurences of a lowercase letter preceded by a '-' with
+	 the Uppercase letter.
+	 Example: --fallback-page becomes fallbackPage:"
+	^((aSwitch replace: '^--' with: '')
+		replace: '-[a-z]' with: [ :each | each second asUppercase ]), ':'
+! !
+
+!FileServer class methodsFor: 'initialization'!
+
+createServerWithArguments: options
+	"If options are empty return a default FileServer instance.
+	 If options are given loop through them and set the passed in values
+	 on the FileServer instance.
+	 
+	 Commanline options map directly to methods in the 'accessing' protocol
+	 taking one parameter.
+	 Adding a method to this protocol makes it directly settable through
+	 command line options.
+	 "
+	| server popFront front optionName optionValue switches |
+
+	switches := self commandLineSwitches.
+
+	server := self new.
+
+	options ifEmpty: [^server].
+
+	(options size even) ifFalse: [
+		console log: 'Using default parameters.'.
+		console log: 'Wrong commandline options or not enough arguments for: ' , options.
+		console log: 'Use any of the following ones: ', switches.
+		^server].
+
+	popFront := [:args |
+		front := args first.
+		args remove: front.
+		front].
+
+	[options notEmpty] whileTrue: [
+		optionName  := popFront value: options.
+		optionValue := popFront value: options.
+
+		(switches includes: optionName) ifTrue: [
+			optionName := self selectorForCommandLineSwitch: optionName.
+			server perform: optionName withArguments: (Array with: optionValue)]
+			ifFalse: [
+				console log: optionName, ' is not a valid commandline option'.
+				console log: 'Use any of the following ones: ', switches ]].
+	^server.
+!
+
+main
+	"Main entry point for Amber applications.
+	 Creates and starts a FileServer instance."
+	| fileServer args |
+	args := process argv.
+	"Remove the first args which contain the path to the node executable and the script file."
+	args removeFrom: 1 to: 3.
+
+	args detect: [ :each |
+		(each = '--help') ifTrue: [FileServer printHelp]]
+	ifNone: [
+		fileServer := FileServer createServerWithArguments: args.
+		^fileServer start]
+! !
+
+Object subclass: #Repl
+	instanceVariableNames: 'readline interface util'
+	package: 'AmberCli'!
+
+!Repl methodsFor: 'accessing'!
+
+prompt
+	^'amber >> '
+! !
+
+!Repl methodsFor: 'actions'!
+
+close
+	process stdin destroy
+!
+
+createInterface
+	"No completion for now"
+	interface := readline createInterface: process stdin stdout: process stdout.
+	interface on: 'line' do: [:buffer  | self eval: buffer].
+	interface on: 'close' do: [self close].
+	self setPrompt.
+	interface prompt
+!
+
+eval: buffer
+	| result |
+	buffer isEmpty ifFalse: [
+		self try: [
+			result := Compiler new evaluateExpression: buffer.
+			Transcript show: result]
+		catch: [:e |
+			e isSmalltalkError
+			    ifTrue: [ErrorHandler new handleError: e]
+			    ifFalse: [process stdout write: e jsStack]]].
+	interface prompt
+!
+
+setPrompt
+	interface setPrompt: self prompt
+! !
+
+!Repl methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	readline := require value: 'readline'.
+	util := require value: 'util'
+! !
+
+!Repl class methodsFor: 'not yet classified'!
+
+main
+	self new createInterface
+! !
+

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini