smalltalk
/
osmo-st-all
Archived
1
0
Fork 0

Imported more files

This commit is contained in:
Nicolas Petton 2010-03-09 18:48:00 +01:00
parent 632562b358
commit 3d0d90bfcf
16 changed files with 1225 additions and 0 deletions

107
Core/Text/GRCodec.st Normal file
View File

@ -0,0 +1,107 @@
GRObject subclass: GRCodec [
<comment: 'A codec defines how Seaside communicates without the outside world and how outside data is converted into the image (decoding) and back outside the image (encoding). The codec is essentially a stream factory that provides wrappers around standard streams. All streams do support binary mode for non-converted transfer.'>
<category: 'Grease-Core-Text'>
GRCodec class >> allCodecs [
"Answer all codecs supported in this system. This is a collection of codec instances."
<category: 'accessing'>
^self subclasses inject: self codecs asArray
into: [:result :each | result , each allCodecs]
]
GRCodec class >> codecs [
"Answer a collection of possible codecs of the receiver. To be overridden by concrete subclasses."
<category: 'accessing'>
^#()
]
GRCodec class >> forEncoding: aString [
"Answer a new codec instance for the given encoding name. Raise an WAUnsupportedEncodingError if the encoding name is not supported by this image."
<category: 'instance creation'>
self allSubclassesDo: [:each |
(each supportsEncoding: aString) ifTrue: [
^each basicForEncoding: aString]].
self unsupportedEncoding: aString
]
GRCodec class >> supportsEncoding: aString [
"Answer whether the the given encoding name is supported by this codec class."
<category: 'testing'>
self subclassResponsibility
]
GRCodec class >> basicForEncoding: aString [
"Create the actual instance."
<category: 'private'>
self subclassResponsibility
]
GRCodec class >> unsupportedEncoding: aString [
"Signal an unsupported encoding."
<category: 'private'>
GRUnsupportedEncodingError signal: 'unsupported encoding: ' , aString
]
name [
"Answer a human readable string of the receivers encoding policy."
<category: 'accessing'>
self subclassResponsibility
]
url [
"Answer a codec that is responsible to encode and decode URLs. In most cases an UTF-8 codec is the only valid choice, but subclasses might decide to do something else."
<category: 'accessing'>
self subclassResponsibility
]
decode: aString [
<category: 'convenience'>
| readStream writeStream |
readStream := self decoderFor: aString readStream.
writeStream := WriteStream on: (String new: aString size).
[readStream atEnd]
whileFalse: [writeStream nextPutAll: (readStream next: 1024)].
^writeStream contents
]
encode: aString [
<category: 'convenience'>
| writeStream |
writeStream := self encoderFor:
(WriteStream on: (String new: aString size)).
writeStream nextPutAll: aString.
^writeStream contents
]
decoderFor: aReadStream [
"Wrap aReadStream with an decoder for the codec of the receiver. Answer a read stream that delegates to and shares the state of aReadStream."
<category: 'conversion'>
self subclassResponsibility
]
encoderFor: aWriteStream [
"Wrap aWriteStream with an encoder for the codec of the receiver. Answer a write stream that delegates to and shares the state of aWriteStream."
<category: 'conversion'>
self subclassResponsibility
]
printOn: aStream [
<category: 'printing'>
super printOn: aStream.
aStream
nextPutAll: ' name: ';
print: self name
]
]

View File

@ -0,0 +1,91 @@
GRObject subclass: GRCodecStream [
| stream |
<comment: 'A WACodecStream is a wrapper around a write stream and defines common behavior.
Instance Variables
stream: <WriteStream>
stream - a WriteStream
'>
<category: 'Grease-Core-Text'>
GRCodecStream class >> on: aStream [
<category: 'instance creation'>
^self basicNew initalizeOn: aStream
]
initalizeOn: aStream [
<category: 'initialization'>
self initialize.
stream := aStream
]
binary [
<category: 'accessing'>
]
contents [
<category: 'accessing'>
^stream contents
]
flush [
<category: 'accessing'>
stream flush
]
size [
<category: 'accessing'>
^stream size
]
text [
<category: 'accessing'>
]
crlf [
<category: 'streaming'>
self
nextPut: Character cr;
nextPut: Character lf
]
next [
<category: 'streaming'>
self subclassResponsibility
]
next: anInteger [
<category: 'streaming'>
self subclassResponsibility
]
nextPut: aCharacter [
<category: 'streaming'>
self subclassResponsibility
]
nextPutAll: aString [
<category: 'streaming'>
self subclassResponsibility
]
space [
<category: 'streaming'>
self nextPut: Character space
]
tab [
<category: 'streaming'>
self nextPut: Character tab
]
atEnd [
<category: 'testing'>
^stream atEnd
]
]

33
Core/Text/GRInflector.st Normal file
View File

@ -0,0 +1,33 @@
GRObject subclass: GRInflector [
<comment: 'The Inflector transforms words from singular to plural.'>
<category: 'Grease-Core-Text'>
InflectionRules := nil.
Uninflected := nil.
GRInflector class >> pluralize: aString [
<category: 'accessing'>
| string |
string := aString asLowercase.
Uninflected do: [:each | (string endsWith: each) ifTrue: [^aString]].
InflectionRules do:
[:rule |
(string endsWith: rule first)
ifTrue: [^(aString allButLast: rule third) , rule second]].
^aString , 's'
]
GRInflector class >> initialize [
<category: 'initialization'>
Uninflected := #('bison' 'bream' 'breeches' 'britches' 'carp' 'chassis' 'clippers' 'cod' 'contretemps' 'corps' 'debris' 'deer' 'diabetes' 'djinn' 'eland' 'elk' 'equipment' 'fish' 'flounder' 'gallows' 'graffiti' 'headquarters' 'herpes' 'high-jinks' 'homework' 'information' 'innings' 'ities' 'itis' 'jackanapes' 'mackerel' 'measles' 'mews' 'money' 'mumps' 'news' 'ois' 'pincers' 'pliers' 'pox' 'proceedings' 'rabies' 'rice' 'salmon' 'scissors' 'sea-bass' 'series' 'shears' 'sheep' 'species' 'swine' 'trout' 'tuna' 'whiting' 'wildebeest').
InflectionRules := #(#('man' 'en' 2) #('child' 'ren' 0) #('cow' 'kine' 3) #('penis' 'es' 0) #('sex' 'es' 0) #('person' 'ople' 4) #('octopus' 'es' 0) #('quiz' 'zes' 0) #('ox' 'en' 0) #('louse' 'ice' 4) #('mouse' 'ice' 4) #('matrix' 'ices' 2) #('vertix' 'ices' 2) #('vertex' 'ices' 2) #('indix' 'ices' 2) #('index' 'ices' 2) #('x' 'es' 0) #('ch' 'es' 0) #('ss' 'es' 0) #('sh' 'es' 0) #('ay' 's' 0) #('ey' 's' 0) #('iy' 's' 0) #('oy' 's' 0) #('uy' 's' 0) #('y' 'ies' 1) #('alf' 'ves' 1) #('elf' 'ves' 1) #('olf' 'ves' 1) #('arf' 'ves' 1) #('nife' 'ves' 2) #('life' 'ves' 2) #('wife' 'ves' 2) #('sis' 'es' 2) #('tum' 'a' 2) #('ium' 'a' 2) #('buffalo' 'es' 0) #('tomato' 'es' 0) #('buffalo' 'es' 0) #('bus' 'es' 0) #('alias' 'es' 0) #('status' 'es' 0) #('octopus' 'i' 2) #('virus' 'i' 2) #('axis' 'es' 2) #('s' '' 0))
]
]
Eval [
GRInflector initialize
]

View File

@ -0,0 +1 @@
GRError subclass: GRInvalidUtf8Error []

View File

@ -0,0 +1,36 @@
GRPrinter subclass: GRMappedPrinter [
| next block |
<comment: nil>
<category: 'Grease-Core-Text'>
GRMappedPrinter class >> block: aBlock next: aPrinter [
<category: 'instance creation'>
^(self new)
block: aBlock;
next: aPrinter;
yourself
]
block: aBlock [
<category: 'accessing'>
block := aBlock
]
next: aPrinter [
<category: 'accessing'>
next := aPrinter
]
initialize [
<category: 'initialization'>
super initialize.
self block: [:value | value]
]
print: anObject on: aStream [
<category: 'printing'>
next print: (block value: anObject) on: aStream
]
]

61
Core/Text/GRNullCodec.st Normal file
View File

@ -0,0 +1,61 @@
GRCodec subclass: GRNullCodec [
<comment: 'The null codec always returns the original streams. It assumes that the outside world uses the same encoding as the inside world. This is highly efficient as no transformation is applied to the data, but has its drawbacks.'>
<category: 'Grease-Core-Text'>
GRNullCodec class >> codecs [
<category: 'accessing'>
^Array with: self new
]
GRNullCodec class >> supportsEncoding: aString [
<category: 'testing'>
^aString isNil
]
GRNullCodec class >> basicForEncoding: aString [
<category: 'private'>
^self new
]
name [
<category: 'accessing'>
^'(none)'
]
url [
"The selfish method. Let's do it with ourselves."
<category: 'accessing'>
^self
]
decode: aString [
"Overridden for efficencey."
<category: 'convenience'>
^aString
]
encode: aString [
"Overridden for efficencey."
<category: 'convenience'>
^aString
]
decoderFor: aReadStream [
"wrap to avoid String vs ByteArray issues"
<category: 'conversion'>
^GRNullCodecStream on: aReadStream
]
encoderFor: aWriteStream [
"wrap to avoid String vs ByteArray issues"
<category: 'conversion'>
^GRNullCodecStream on: aWriteStream
]
]

View File

@ -0,0 +1,37 @@
GRCodecStream subclass: GRNullCodecStream [
<comment: 'A WANullCodecStream is a WriteStream on a String on which you can both put binary and character data without encoding happening.
Instance Variables
stream: <WriteStream>
stream
- a WriteStream on a String'>
<category: 'Grease-Core-Text'>
next [
<category: 'streaming'>
^stream next
]
next: anInteger [
<category: 'streaming'>
^stream next: anInteger
]
nextPut: aCharacterOrByte [
<category: 'streaming'>
aCharacterOrByte isCharacter
ifTrue: [stream nextPut: aCharacterOrByte]
ifFalse: [stream nextPut: (Character codePoint: aCharacterOrByte)]
]
nextPutAll: aStringOrByteArray [
<category: 'streaming'>
aStringOrByteArray isString
ifTrue: [stream nextPutAll: aStringOrByteArray]
ifFalse: [1
to: aStringOrByteArray size
do: [:index | stream nextPut: (Character codePoint: (aStringOrByteArray at: index))]]
]
]

View File

@ -0,0 +1,228 @@
GRPrinter subclass: GRNumberPrinter [
| characters base delimiter digits infinite nan padding accuracy precision separator |
<comment: 'A GRNumberPrinter is prints numbers (integers and floats) in various formats in a platform independent way.
Instance Variables
accuracy: <UndefinedObject|Float>
base: <Integer>
delimiter: <UndefinedObject|Charater>
digits: <UndefinedObject|Integer>
infinite: <UndefinedObject|String>
nan: <UndefinedObject|String>
padding: <UndefinedObject|Charater>
precision: <Integer>
separator: <UndefinedObject|Charater>'>
<category: 'Grease-Core-Text'>
NumbersToCharactersLowercase := nil.
NumbersToCharactersUppercase := nil.
GRNumberPrinter class >> initialize [
<category: 'initialization'>
NumbersToCharactersLowercase := '0123456789abcdefghijklmnopqrstuvwxyz'.
NumbersToCharactersUppercase := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
]
accuracy: aFloat [
"Round towards the nearest number that is a multiple of aFloat."
<category: 'accessing'>
accuracy := aFloat
]
base: anInteger [
"The numeric base to which the number should be printed."
<category: 'accessing'>
base := anInteger
]
characters: aString [
"The characters to be used to convert a number to a string."
<category: 'accessing'>
characters := aString
]
delimiter: aCharacter [
"The delimiter to separate the integer and fraction part of the number."
<category: 'accessing'>
delimiter := aCharacter
]
digits: anInteger [
"The number of digits to be printed in the integer part."
<category: 'accessing'>
digits := anInteger
]
infinite: aString [
"The string that should be displayed if the number is positive or negative infinity."
<category: 'accessing'>
infinite := aString
]
nan: aString [
"The string that should be displayed if the number is not a number."
<category: 'accessing'>
nan := aString
]
padding: aCharacter [
"The padding for the integer part."
<category: 'accessing'>
padding := aCharacter
]
precision: anInteger [
"The number of digits to be printed in the fraction part."
<category: 'accessing'>
precision := anInteger
]
separator: aCharacter [
"Separator character to be used to group digits."
<category: 'accessing'>
separator := aCharacter
]
lowercase [
"Use lowercase characters for numbers of base 10 and higher."
<category: 'actions'>
self characters: NumbersToCharactersLowercase
]
uppercase [
"Use uppercase characters for numbers of base 10 and higher."
<category: 'actions'>
self characters: NumbersToCharactersUppercase
]
initialize [
<category: 'initialization'>
super initialize.
self lowercase.
self base: 10.
self delimiter: $..
self infinite: 'Infinite'.
self nan: 'NaN'.
self padding: $ .
self precision: 0
]
print: aNumber on: aStream [
<category: 'printing'>
aNumber isNaN ifTrue: [^self printNaN: aNumber on: aStream].
aNumber isInfinite ifTrue: [^self printInfinite: aNumber on: aStream].
precision = 0
ifTrue: [self printInteger: aNumber on: aStream]
ifFalse: [self printFloat: aNumber on: aStream]
]
printFloat: aNumber on: aStream [
<category: 'printing'>
| multiplier rounded |
multiplier := base asFloat raisedTo: precision.
rounded := aNumber roundTo: (accuracy ifNil: [1.0 / multiplier]).
self printInteger: rounded on: aStream.
delimiter isNil ifFalse: [aStream nextPut: delimiter].
self printFraction: rounded fractionPart abs * multiplier on: aStream
]
printFraction: aNumber on: aStream [
<category: 'printing'>
| result |
result := self
pad: (self digitsOf: aNumber rounded base: base)
left: $0
to: precision.
separator isNil ifFalse: [result := self separate: result left: separator].
aStream nextPutAll: result
]
printInfinite: aNumber on: aStream [
<category: 'printing'>
infinite isNil ifFalse: [aStream nextPutAll: infinite]
]
printInteger: aNumber on: aStream [
<category: 'printing'>
| result |
result := self digitsOf: aNumber integerPart base: base.
separator isNil
ifFalse: [result := self separate: result right: separator].
(digits isNil or: [padding isNil])
ifFalse: [result := self
pad: result
left: padding
to: digits].
aStream nextPutAll: result
]
printNaN: anInteger on: aStream [
<category: 'printing'>
nan isNil ifFalse: [aStream nextPutAll: nan]
]
digitsOf: aNumber base: aBaseInteger [
"Answer the absolute digits of aNumber in the base aBaseInteger."
<category: 'utilities'>
| integer stream next |
integer := aNumber truncated abs.
integer = 0 ifTrue: [^'0'].
stream := WriteStream on: (String new: 10).
[integer > 0] whileTrue:
[next := integer quo: aBaseInteger.
stream nextPut: (characters at: 1 + integer - (next * aBaseInteger)).
integer := next].
^stream contents reversed
]
separate: aString left: aCharacter [
"Separate from the left side every 3 characters with aCharacter."
<category: 'utilities'>
| size stream |
size := aString size.
stream := WriteStream on: (String new: 2 * size).
1
to: size
do: [:index |
(index ~= 1 and: [index \\ 3 = 1]) ifTrue: [stream nextPut: aCharacter].
stream nextPut: (aString at: index)].
^stream contents
]
separate: aString right: aCharacter [
"Separate from the right side every 3 characters with aCharacter."
<category: 'utilities'>
| size stream |
size := aString size.
stream := WriteStream on: (String new: 2 * size).
1
to: size
do: [:index |
(index ~= 1 and: [(size - index) \\ 3 = 2])
ifTrue: [stream nextPut: aCharacter].
stream nextPut: (aString at: index)].
^stream contents
]
]
Eval [
GRNumberPrinter initialize
]

View File

@ -0,0 +1,24 @@
Eval [
'From PharoCore1.0rc1 of 19 October 2009 [Latest update: #10505] on 9 March 2010 at 6:38:04 pm'
]
GRPrinter subclass: GROrdinalizePrinter [
<comment: nil>
<category: 'Grease-Core-Text'>
print: anObject on: aStream [
<category: 'printing'>
aStream nextPutAll: (self ordinalize: anObject integerPart)
]
ordinalize: anInteger [
<category: 'private'>
^(anInteger \\ 100 between: 11 and: 13)
ifTrue: ['th']
ifFalse: [#('st' 'nd' 'rd') at: anInteger \\ 10 ifAbsent: ['th']]
]
]

View File

@ -0,0 +1,28 @@
GRPrinter subclass: GRPluggablePrinter [
| block |
<comment: nil>
<category: 'Grease-Core-Text'>
GRPluggablePrinter class >> on: aBlock [
<category: 'instance creation'>
^self new block: aBlock
]
block: aBlock [
<category: 'accessing'>
block := aBlock
]
initialize [
<category: 'initialization'>
super initialize.
self block: [:value | String new]
]
print: anObject on: aStream [
<category: 'printing'>
aStream nextPutAll: (block value: anObject)
]
]

328
Core/Text/GRPrinter.st Normal file
View File

@ -0,0 +1,328 @@
GRObject subclass: GRPrinter [
<comment: nil>
<category: 'Grease-Core-Text'>
GRPrinter class >> cookieTimestamp [
"Netscape's original proposal defined an Expires header that took a date value in a fixed-length variant format in place of Max-Age: Wdy, DD-Mon-YY HH:MM:SS GMT"
<category: 'factory'>
^GRMappedPrinter block: [:timestamp | timestamp asUTC]
next: self abbreviatedWeekName , ', ' , self paddedDay , '-'
, self abbreviatedMonthName , '-'
, self paddedYear , ' '
, self isoTime , ' GMT'
]
GRPrinter class >> httpDate [
"Answers a printer that formats dates for HTTP1.1 (RFC 2616)"
<category: 'factory'>
^self rfc1123
]
GRPrinter class >> isoDate [
"Ansers a printer that formats dates accoring to ISO(YYYY-MM-DD) E.g.
2003-12-24"
<category: 'factory'>
^self paddedYear , $- , self paddedMonth , $- , self paddedDay
]
GRPrinter class >> isoTime [
"Ansers a printer that formats time accoring to ISO(HH:MM:SS) E.g.
12:23:34"
<category: 'factory'>
^self paddedHour24 , $: , self paddedMinute , $: , self paddedSecond
]
GRPrinter class >> rfc1123 [
"Answers a printer that formats dates for HTTP1.1 (RFC 1123). Eg.
Sun, 06 Nov 1994 08:49:37 GMT"
<category: 'factory'>
^GRMappedPrinter block:
[:date |
"For the purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal Time)"
date asUTC]
next: GRSequentialPrinter new , self abbreviatedWeekName , ', '
, self paddedDay , Character space
, self abbreviatedMonthName , Character space
, self paddedYear , Character space
, self isoTime , ' GMT'
]
GRPrinter class >> rfc822 [
"Answers a privter that formats dates according to RFC 822 (email). Eg.
Sun, 31 Aug 2008 19:41:46 +0200"
<category: 'factory'>
^self abbreviatedWeekName , ', ' , self paddedDay , Character space
, self abbreviatedMonthName , Character space
, self paddedYear , Character space
, self isoTime , Character space
, self offsetSign , self absOffsetHoursPadded
, self absOffsetMinutesPadded
]
GRPrinter class >> rfc822WithTimeZone: aString [
"Answers a privter that formats dates according to RFC 822 (email) with the given time zone String. Eg.
Sun, 31 Aug 2008 19:41:46 <aString>"
<category: 'factory'>
^self abbreviatedWeekName , ', ' , self paddedDay , Character space
, self abbreviatedMonthName , Character space
, self paddedYear , Character space
, self isoTime , Character space
, aString
]
GRPrinter class >> swissCurrency [
<category: 'factory'>
^GRSequentialPrinter new , 'CHF ' , GRSignPrinter new
, ((GRNumberPrinter new)
separator: $';
precision: 2;
accuracy: 0.05;
yourself)
]
GRPrinter class >> usCurrency [
<category: 'factory'>
^GRSignPrinter new , $$ , ((GRNumberPrinter new)
separator: $,;
precision: 2;
yourself)
]
GRPrinter class >> abbreviatedMonthName [
<category: 'parts-date'>
^self
monthName: #('Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov' 'Dec')
]
GRPrinter class >> abbreviatedWeekName [
<category: 'parts-date'>
^self weekName: #('Sun' 'Mon' 'Tue' 'Wed' 'Thu' 'Fri' 'Sat')
]
GRPrinter class >> absOffsetHoursPadded [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date offset hours abs]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> absOffsetMinutesPadded [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date offset minutes abs]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> fullMonthName [
<category: 'parts-date'>
^self
monthName: #('January' 'February' 'March' 'April' 'May' 'June' 'July' 'August' 'September' 'October' 'November' 'December')
]
GRPrinter class >> fullWeekName [
<category: 'parts-date'>
^self
weekName: #('Sunday' 'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday' 'Saturday')
]
GRPrinter class >> monthName: anArray [
<category: 'parts-date'>
^GRPluggablePrinter on: [:date | anArray at: date monthIndex]
]
GRPrinter class >> offsetSign [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date offset]
next: ((GRSignPrinter new)
positivePrinter: $+;
negativePrinter: $-;
yourself)
]
GRPrinter class >> paddedCentury [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date year \\ 100]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> paddedDay [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date dayOfMonth]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> paddedMonth [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date monthIndex]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> paddedYear [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date year]
next: (self numberWithAtLeastDigits: 4)
]
GRPrinter class >> unpaddedCentury [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date year \\ 100]
next: GRNumberPrinter new
]
GRPrinter class >> unpaddedDay [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date dayOfMonth] next: GRNumberPrinter new
]
GRPrinter class >> unpaddedMonth [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date monthIndex] next: GRNumberPrinter new
]
GRPrinter class >> unpaddedYear [
<category: 'parts-date'>
^GRMappedPrinter block: [:date | date year] next: GRNumberPrinter new
]
GRPrinter class >> weekName: anArray [
<category: 'parts-date'>
^GRPluggablePrinter on: [:date | anArray at: date dayOfWeek]
]
GRPrinter class >> paddedHour12 [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | (time hour - 1) \\ 12 + 1]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> paddedHour24 [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | time hour]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> paddedMinute [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | time minute]
next: (self numberWithAtLeastDigits: 2)
]
GRPrinter class >> paddedSecond [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | time second]
next: ((GRNumberPrinter new)
padding: $0;
digits: 2)
]
GRPrinter class >> unpaddedHour12 [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | (time hour - 1) \\ 12 + 1]
next: GRNumberPrinter new
]
GRPrinter class >> unpaddedHour24 [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | time hour] next: GRNumberPrinter new
]
GRPrinter class >> unpaddedMinute [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | time minute] next: GRNumberPrinter new
]
GRPrinter class >> unpaddedSecond [
<category: 'parts-time'>
^GRMappedPrinter block: [:time | time second] next: GRNumberPrinter new
]
GRPrinter class >> binaryFileSize [
<category: 'parts-units'>
^GRUnitPrinter base: 1024
units: #('byte' 'bytes' 'KiB' 'MiB' 'GiB' 'TiB' 'PiB' 'EiB' 'ZiB' 'YiB')
]
GRPrinter class >> decimalFileSize [
<category: 'parts-units'>
^GRUnitPrinter base: 1000
units: #('byte' 'bytes' 'kB' 'MB' 'GB' 'TB' 'PB' 'EB' 'ZB' 'YB')
]
GRPrinter class >> numberWithAtLeastDigits: anInteger [
<category: 'parts-units'>
^(GRNumberPrinter new)
padding: $0;
digits: anInteger;
yourself
]
, aPrinter [
<category: 'operators'>
^GRSequentialPrinter new , self , aPrinter
]
print: anObject [
<category: 'printing'>
^String streamContents: [:stream | self print: anObject on: stream]
]
print: anObject on: aStream [
"Subclasses override this method to produce some output."
<category: 'printing'>
]
pad: aString center: aCharacter to: anInteger [
"Pad to the center of aString with aCharacter to at least anInteger characters."
<category: 'utilities'>
| result index |
anInteger <= aString size ifTrue: [^aString].
index := (anInteger - aString size) // 2.
result := (String new: anInteger) atAllPut: aCharacter.
result
replaceFrom: index + 1
to: index + aString size
with: aString
startingAt: 1.
^result
]
pad: aString left: aCharacter to: anInteger [
"Pad to the left side of aString with aCharacter to at least anInteger characters."
<category: 'utilities'>
| result |
anInteger <= aString size ifTrue: [^aString].
result := (String new: anInteger) atAllPut: aCharacter.
result
replaceFrom: anInteger - aString size + 1
to: anInteger
with: aString
startingAt: 1.
^result
]
pad: aString right: aCharacter to: anInteger [
"Pad to the right side of aString with aCharacter to at least anInteger characters."
<category: 'utilities'>
| result |
anInteger <= aString size ifTrue: [^aString].
result := (String new: anInteger) atAllPut: aCharacter.
result
replaceFrom: 1
to: aString size
with: aString
startingAt: 1.
^result
]
]

View File

@ -0,0 +1,22 @@
GRPrinter subclass: GRSequentialPrinter [
| parts |
<comment: nil>
<category: 'Grease-Core-Text'>
initialize [
<category: 'initialization'>
super initialize.
parts := OrderedCollection new
]
, aConverter [
<category: 'operators'>
parts add: aConverter
]
print: anObject on: aStream [
<category: 'printing'>
parts do: [:each | each print: anObject on: aStream]
]
]

View File

@ -0,0 +1,35 @@
GRPrinter subclass: GRSignPrinter [
| negativePrinter positivePrinter |
<comment: nil>
<category: 'Grease-Core-Text'>
negativePrinter: aPrinter [
"The printer to be used when the number is negative."
<category: 'accessing'>
negativePrinter := aPrinter
]
positivePrinter: aPrinter [
"The printer to be used when the number is zero or positive."
<category: 'accessing'>
positivePrinter := aPrinter
]
initialize [
<category: 'initialization'>
super initialize.
self negativePrinter: $-.
self positivePrinter: nil
]
print: anObject on: aStream [
<category: 'printing'>
anObject negative
ifTrue: [negativePrinter print: anObject on: aStream]
ifFalse: [positivePrinter print: anObject on: aStream]
]
]

View File

@ -0,0 +1,106 @@
GRPrinter subclass: GRStringPrinter [
| trim length pad character |
<comment: nil>
<category: 'Grease-Core-Text'>
character: aCharacter [
"The character to pad the string with."
<category: 'accessing'>
character := aCharacter
]
length: anInteger [
"The maximal size of the string, or the size to pad to."
<category: 'accessing'>
length := anInteger
]
initialize [
<category: 'initialization'>
super initialize.
self
character: $ ;
length: nil.
self
trimNone;
padNone
]
padCenter [
"Pad to the center."
<category: 'padding'>
pad := #pad:center:to:
]
padLeft [
"Pad to the left."
<category: 'padding'>
pad := #pad:left:to:
]
padNone [
"Do not pad the input."
<category: 'padding'>
pad := nil
]
padRight [
"Pad to the right."
<category: 'padding'>
pad := #pad:right:to:
]
print: anObject on: aStream [
<category: 'printing'>
| string |
string := anObject greaseString.
trim isNil ifFalse: [string := string perform: trim].
length isNil
ifFalse: [
length < string size ifTrue: [string := string copyFrom: 1 to: length].
(pad isNil or: [character isNil])
ifFalse: [
string := self
perform: pad
with: string
with: character
with: length]].
aStream nextPutAll: string
]
trimBoth [
"Trim to the left and to the right."
<category: 'trimming'>
trim := #trimBoth
]
trimLeft [
"Trim to the left and to the right."
<category: 'trimming'>
trim := #trimLeft
]
trimNone [
"Do not trim the input."
<category: 'trimming'>
trim := nil
]
trimRight [
"Trim to the left and to the right."
<category: 'trimming'>
trim := #trimRight
]
]

View File

@ -0,0 +1,82 @@
Eval [
'From PharoCore1.0rc1 of 19 October 2009 [Latest update: #10505] on 9 March 2010 at 6:45:25 pm'
]
GRPrinter subclass: GRUnitPrinter [
| integerPrinter fractionPrinter units base |
<comment: nil>
<category: 'Grease-Core-Text'>
GRUnitPrinter class >> base: anInteger units: anArray [
<category: 'instance creation'>
^(self new)
base: anInteger;
units: anArray;
yourself
]
base: anInteger [
<category: 'accessing'>
base := anInteger
]
fractionPrinter: aPrinter [
<category: 'accessing'>
fractionPrinter := aPrinter
]
integerPrinter: aPrinter [
<category: 'accessing'>
integerPrinter := aPrinter
]
units: anArray [
<category: 'accessing'>
units := anArray
]
initialize [
<category: 'initialization'>
super initialize.
self integerPrinter: ((GRNumberPrinter new)
precision: 0;
yourself).
self fractionPrinter: ((GRNumberPrinter new)
precision: 1;
yourself)
]
print: anObject on: aStream [
<category: 'printing'>
anObject = 1
ifTrue:
[^self
print: anObject
unit: units first
on: aStream].
units allButFirst inject: anObject asFloat
into:
[:value :each |
value < base
ifFalse: [value / base]
ifTrue:
[^self
print: value
unit: each
on: aStream]]
]
print: aNumber unit: aString on: aStream [
<category: 'printing'>
(units first = aString or: [units second = aString])
ifTrue: [integerPrinter print: aNumber on: aStream]
ifFalse: [fractionPrinter print: aNumber on: aStream].
aStream
nextPut: $ ;
nextPutAll: aString
]
]

View File

@ -0,0 +1,6 @@
GRError subclass: GRUnsupportedEncodingError [
<comment: nil>
<category: 'Grease-Core-Text'>
]