SystemOrganization addCategory: #'PrettyPetit-Core'! SystemOrganization addCategory: #'PrettyPetit-Tests'! !String methodsFor: '*prettypetit-core-converting' stamp: 'lr 3/11/2010 09:00'! asDocument ^ PPTextDocument string: self! ! !Object methodsFor: '*prettypetit-converting' stamp: 'lr 3/11/2010 14:21'! asDocument ^ PPTextDocument string: self printString! ! Object subclass: #PPDocument instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPDocument commentStamp: 'lr 3/11/2010 13:08' prior: 0! An abstract document.! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 14:18'! + aDocument "Concatenate the receiver and aDocument with a non-breaking space in between." ^ self , ' ' asDocument , aDocument! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 11:57'! , aDocument "Concatenate the receiver and aDocument." ^ PPSequenceDocument with: self with: aDocument! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 09:37'! / aDocument "Concatenate the receiver and aDocument with a softline in between. This effectively puts the receiver and aDocument either next to each other with a aspace inbetween or underneath each other." ^ self , PPLineDocument softline , aDocument! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 09:37'! // aDocument "Concatenate the receiver and aDocument with a softbreak in between. This effectively puts the receiver and aDocument either right next to each other or underneath each other." ^ self , PPLineDocument softbreak , aDocument! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 09:37'! \ aDocument "Concatenate the receiver and aDocument with a line in between." ^ self , PPLineDocument line , aDocument! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 09:37'! \\ aDocument "Concatenate the receiver and aDocument with a linebreak in between." ^ self , PPLineDocument linebreak , aDocument! ! !PPDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:30'! accept: aVisitor "Inform ther renderer of the kind of the node, so that it can do whatever it wants." self subclassResponsibility! ! !PPDocument methodsFor: 'private' stamp: 'lr 3/11/2010 13:08'! addTo: aSequenceDocument aSequenceDocument add: self! ! !PPDocument methodsFor: 'operations-alignment' stamp: 'lr 3/11/2010 17:07'! align "Align the receiver with the nesting level set to the current column." ^ PPColumnDocument block: [ :column | PPNestingDocument block: [ :nesting | self nest: column - nesting ] ]! ! !PPDocument methodsFor: 'converting' stamp: 'lr 3/11/2010 10:13'! asDocument ^ self! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:14'! encloseIn: anObject "Enclose the receiving document with anObject at the beginning and end." ^ self encloseIn: anObject and: anObject! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:16'! encloseIn: aLeftObject and: aRightObject "Enclose the receiving document in aLeftObject and aRightObject." ^ aLeftObject asDocument , self , aRightObject asDocument! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:14'! encloseInAngles "Enclose the receiver in angle brackets." ^ self encloseIn: $< and: $>! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:15'! encloseInBraces "Enclose the receiver in curly braces." ^ self encloseIn: ${ and: $}! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:15'! encloseInBrackets "Enclose the receiver in square brackets." ^ self encloseIn: $[ and: $]! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:19'! encloseInDoubleQuotes "Enclose the receiver in double quotes." ^ self encloseIn: $"! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:15'! encloseInParens "Enclose the receiver in parenthesis." ^ self encloseIn: $( and: $)! ! !PPDocument methodsFor: 'operations-enclose' stamp: 'lr 3/11/2010 14:19'! encloseInSingleQuotes "Enclose the receiver in single quotes." ^ self encloseIn: $'! ! !PPDocument methodsFor: 'operations-fillers' stamp: 'lr 3/11/2010 10:06'! fill: anInteger "Answer the receiver with spaces appended until the width is equal to anInteger." ^ self width: [ :width | width >= anInteger ifTrue: [ PPEmptyDocument new ] ifFalse: [ PPTextDocument spaces: anInteger - width ] ]! ! !PPDocument methodsFor: 'operations-fillers' stamp: 'lr 3/11/2010 17:07'! fillBreak: anInteger "Answer the receiver with spaces appended until the width is equal to anInteger. If the width of x is already larger than i, the nesting level is increased by i and a line is appended. " ^ self width: [ :width | width > anInteger ifTrue: [ PPLineDocument linebreak nest: anInteger ] ifFalse: [ PPTextDocument spaces: anInteger - width ] ]! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/10/2010 21:59'! flatten "Answer a flattened representation of the receiver." ^ self! ! !PPDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 09:26'! group "Answer the receiver with all line breaks undone or without changes." ^ PPUnionDocument with: self flatten with: self! ! !PPDocument methodsFor: 'operations-alignment' stamp: 'lr 3/11/2010 17:07'! hang: anInteger "Align the receiver with the nesting level set to the current column plus anInteger." ^ (self nest: anInteger) align! ! !PPDocument methodsFor: 'operations-alignment' stamp: 'lr 3/11/2010 17:08'! indent: anInteger "Indent the receiver with anInteger spaces." ^ ((PPTextDocument spaces: anInteger) , self) hang: anInteger! ! !PPDocument methodsFor: 'operations-alignment' stamp: 'lr 3/11/2010 17:08'! nest: anInteger "Answer a document that displays the receiver with the current nesting level increased by anInteger." ^ anInteger = 0 ifTrue: [ self ] ifFalse: [ PPNestDocument amount: anInteger document: self ]! ! !PPDocument methodsFor: 'printing' stamp: 'lr 3/11/2010 20:06'! printFormatOn: aStream PPCompactFormatter new stream: aStream; start: self! ! !PPDocument methodsFor: 'printing' stamp: 'lr 3/11/2010 11:08'! printOn: aStream super printOn: aStream. aStream nextPut: $(. self printFormatOn: aStream. aStream nextPut: $)! ! !PPDocument methodsFor: 'operations-fillers' stamp: 'lr 3/11/2010 20:04'! width: aBlock ^ PPColumnDocument block: [ :first | PPSequenceDocument with: self with: (PPColumnDocument block: [ :second | aBlock value: second - first ]) ]! ! PPDocument subclass: #PPEmptyDocument instanceVariableNames: '' classVariableNames: 'Default' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPEmptyDocument commentStamp: 'lr 3/11/2010 13:08' prior: 0! An empty document.! !PPEmptyDocument class methodsFor: 'initialization' stamp: 'lr 3/10/2010 22:05'! initialize Default := self basicNew! ! !PPEmptyDocument class methodsFor: 'instance creation' stamp: 'lr 3/10/2010 22:05'! new ^ Default! ! !PPEmptyDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:30'! accept: aVisitor ^ aVisitor acceptEmptyDocument: self! ! !PPEmptyDocument methodsFor: 'private' stamp: 'lr 3/11/2010 13:09'! addTo: aSequenceDocument "Do not add the empty document to a sequence."! ! !PPEmptyDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 09:17'! group ^ self! ! !PPEmptyDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 17:07'! nest: anInteger ^ self! ! PPDocument subclass: #PPLineDocument instanceVariableNames: 'break' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPLineDocument commentStamp: 'lr 3/11/2010 13:14' prior: 0! A new line.! !PPLineDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 09:33'! line "Answer a document that advances to the next line and indents to the current nesting level. It behaves like an a space if the document is flattened." ^ self basicNew initializeBreak: false! ! !PPLineDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 09:33'! linebreak "Answer a document that advances to the next line and indents to the current nesting level. It disappears if the document is flattened." ^ self basicNew initializeBreak: true! ! !PPLineDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 09:35'! softbreak "Answer a document that is discarded if the resulting output fits the page, otherwise behave like #line." ^ self linebreak group! ! !PPLineDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 09:34'! softline "Answer a document that behaves like a space if the output fits the page, otherwise behaves like #line." ^ self line group! ! !PPLineDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:30'! accept: aVisitor ^ aVisitor acceptLineDocument: self! ! !PPLineDocument methodsFor: 'actions' stamp: 'lr 3/10/2010 22:12'! flatten ^ break ifTrue: [ PPEmptyDocument new ] ifFalse: [ PPTextDocument string: ' ' ]! ! !PPLineDocument methodsFor: 'initialization' stamp: 'lr 3/11/2010 09:16'! initializeBreak: aBoolean break := aBoolean! ! PPDocument subclass: #PPListDocument instanceVariableNames: 'documents' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPListDocument commentStamp: 'lr 3/11/2010 13:11' prior: 0! An abstract list of documents.! !PPListDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 11:59'! new ^ self withAll: OrderedCollection new! ! !PPListDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 17:26'! with: aDocument ^ self withAll: (OrderedCollection with: aDocument)! ! !PPListDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 11:59'! with: aFirstDocument with: aSecondDocument ^ self withAll: (OrderedCollection with: aFirstDocument with: aSecondDocument)! ! !PPListDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 11:59'! withAll: aCollection ^ self basicNew initializeWithAll: aCollection asOrderedCollection! ! !PPListDocument methodsFor: 'accessing' stamp: 'lr 3/10/2010 22:06'! documents ^ documents! ! !PPListDocument methodsFor: 'initialization' stamp: 'lr 3/11/2010 11:59'! initializeWithAll: anOrderedCollection documents := anOrderedCollection! ! PPListDocument subclass: #PPSequenceDocument instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPSequenceDocument commentStamp: 'lr 3/11/2010 13:11' prior: 0! A document sequence.! !PPSequenceDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 15:10'! , anObject anObject asDocument addTo: self! ! !PPSequenceDocument methodsFor: 'private' stamp: 'lr 3/11/2010 11:58'! accept: aVisitor ^ aVisitor acceptSequenceDocument: self! ! !PPSequenceDocument methodsFor: 'adding' stamp: 'lr 3/11/2010 12:47'! add: aDocument documents addLast: aDocument! ! !PPSequenceDocument methodsFor: 'adding' stamp: 'lr 3/11/2010 12:47'! addAll: aCollection documents addAll: aCollection! ! !PPSequenceDocument methodsFor: 'operations-concate' stamp: 'lr 3/11/2010 17:58'! concate "Concate the documents of the receiver horizontally if they fit, otherwise separate vertically." ^ self concateVertical group! ! !PPSequenceDocument methodsFor: 'operations-concate' stamp: 'lr 3/11/2010 17:56'! concateFill "Concate the documents of the receiver horizontally as long as they fit the page, then insert a newline." ^ self fold: [ :a :b | a // b ]! ! !PPSequenceDocument methodsFor: 'operations-concate' stamp: 'lr 3/11/2010 17:55'! concateHorizontal "Concate the documents of the receiver horizontally." ^ self! ! !PPSequenceDocument methodsFor: 'operations-concate' stamp: 'lr 3/11/2010 17:57'! concateVertical "Conate the documents of the receiver vertically separated by a newline. If a group undoes the newlines the documents are directly concated." ^ self fold: [ :a :b | a \\ b ]! ! !PPSequenceDocument methodsFor: 'actions' stamp: 'lr 3/11/2010 13:20'! flatten ^ self class new addAll: (self documents collect: [ :each | each flatten ]); yourself! ! !PPSequenceDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 17:24'! fold: aBlock | sequence | documents isEmpty ifTrue: [ ^ PPEmptyDocument new ]. documents size = 1 ifTrue: [ ^ documents first ]. sequence := self class with: documents first. 2 to: documents size do: [ :index | sequence := aBlock value: sequence value: (documents at: index) ]. ^ sequence! ! !PPSequenceDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 18:03'! punctuate: aDocument ^ self fold: [ :a :b | a , aDocument , b ]! ! !PPSequenceDocument methodsFor: 'operations-separate' stamp: 'lr 3/11/2010 17:50'! separate "Separate the documents of the receiver horizontally separated by a space if they fit, otherwise separate vertically." ^ self separateVertical group! ! !PPSequenceDocument methodsFor: 'operations-separate' stamp: 'lr 3/11/2010 17:57'! separateFill "Separate the documents of the receiver horizontally by a space as long as they fit the page, then insert a newline." ^ self fold: [ :a :b | a / b ]! ! !PPSequenceDocument methodsFor: 'operations-separate' stamp: 'lr 3/11/2010 17:49'! separateHorizontal "Separate the documents of the receiver horizontally separated by a space." ^ self fold: [ :a :b | a + b ]! ! !PPSequenceDocument methodsFor: 'operations-separate' stamp: 'lr 3/11/2010 17:49'! separateVertical "Separate the documents of the receiver vertically separated by a newline. If a group undoes the newlines the documents remain separated by spaces." ^ self fold: [ :a :b | a \ b ]! ! PPListDocument subclass: #PPUnionDocument instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPUnionDocument commentStamp: 'lr 3/11/2010 13:17' prior: 0! A document union. Do not use this class directly, it has two invariants that need to be fulfilled at all times: (1) all documents are required to flatten to the same layout, and (2) the documents are sorted by increasing length of their first line.! !PPUnionDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:31'! accept: aVisitor ^ aVisitor acceptUnionDocument: self! ! !PPUnionDocument methodsFor: 'actions' stamp: 'lr 3/11/2010 13:21'! flatten ^ self documents isEmpty ifTrue: [ PPEmptyDocument new ] ifFalse: [ self documents first flatten ]! ! PPDocument subclass: #PPNestDocument instanceVariableNames: 'amount document' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPNestDocument class methodsFor: 'instance creation' stamp: 'lr 3/11/2010 13:13'! amount: anInteger document: aDocument ^ self basicNew initializeAmount: anInteger document: aDocument! ! !PPNestDocument methodsFor: 'private' stamp: 'lr 3/11/2010 17:06'! accept: aVisitor ^ aVisitor acceptNestDocument: self! ! !PPNestDocument methodsFor: 'accessing' stamp: 'lr 3/11/2010 13:13'! amount ^ amount! ! !PPNestDocument methodsFor: 'accessing' stamp: 'lr 3/11/2010 09:46'! document ^ document! ! !PPNestDocument methodsFor: 'initialization' stamp: 'lr 3/11/2010 13:13'! initializeAmount: anInteger document: aDocument amount := anInteger. document := aDocument! ! !PPNestDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 17:07'! nest: anInteger ^ document nest: amount + anInteger! ! PPDocument subclass: #PPPluggableDocument instanceVariableNames: 'block' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! PPPluggableDocument subclass: #PPColumnDocument instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPColumnDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:31'! accept: aVisitor ^ aVisitor acceptColumnDocument: self! ! PPPluggableDocument subclass: #PPNestingDocument instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPNestingDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:31'! accept: aVisitor ^ aVisitor acceptNestingDocument: self! ! !PPPluggableDocument class methodsFor: 'instance creation' stamp: 'lr 3/10/2010 22:07'! block: aBlock ^ self basicNew initializeBlock: aBlock! ! !PPPluggableDocument methodsFor: 'accessing' stamp: 'lr 3/11/2010 09:46'! block ^ block! ! !PPPluggableDocument methodsFor: 'actions' stamp: 'lr 3/10/2010 22:05'! flatten ^ self class block: [ :each | (block value: each) flatten ]! ! !PPPluggableDocument methodsFor: 'initialization' stamp: 'lr 3/10/2010 22:07'! initializeBlock: aBlock block := aBlock! ! PPDocument subclass: #PPTextDocument instanceVariableNames: 'string' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPTextDocument class methodsFor: 'initialization' stamp: 'lr 3/11/2010 09:57'! spaces: anInteger ^ self string: (String new: anInteger withAll: $ )! ! !PPTextDocument class methodsFor: 'initialization' stamp: 'lr 3/10/2010 22:08'! string: aString ^ self basicNew initializeString: aString! ! !PPTextDocument methodsFor: 'private' stamp: 'lr 3/10/2010 22:31'! accept: aVisitor ^ aVisitor acceptTextDocument: self! ! !PPTextDocument methodsFor: 'initialization' stamp: 'lr 3/10/2010 22:09'! initializeString: aString string := aString! ! !PPTextDocument methodsFor: 'operations' stamp: 'lr 3/11/2010 17:07'! nest: anInteger ^ self! ! !PPTextDocument methodsFor: 'accessing' stamp: 'lr 3/11/2010 09:46'! size ^ string size! ! !PPTextDocument methodsFor: 'accessing' stamp: 'lr 3/11/2010 09:05'! string ^ string! ! Object subclass: #PPFormatter instanceVariableNames: 'stream' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! PPFormatter subclass: #PPCompactFormatter instanceVariableNames: 'indent' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPCompactFormatter commentStamp: 'lr 3/11/2010 13:18' prior: 0! Format a document without unnecessary indentation. As there is no sophisticated pretty printing involved here the formatting is very fast. The resulting output contains fewer characters and is intended for machine reading only.! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 08:57'! acceptColumnDocument: aDocument self visit: (aDocument block value: indent)! ! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 09:48'! acceptLineDocument: aDocument indent := 0. stream cr! ! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 17:06'! acceptNestDocument: aDocument self visit: aDocument document! ! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 08:57'! acceptNestingDocument: aDocument self visit: (aDocument block value: 0)! ! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 11:58'! acceptSequenceDocument: aDocument self visitAll: aDocument documents! ! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 09:48'! acceptTextDocument: aDocument indent := indent + aDocument size. stream nextPutAll: aDocument string! ! !PPCompactFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 08:26'! acceptUnionDocument: aDocument self visit: aDocument documents last! ! !PPCompactFormatter methodsFor: 'visiting' stamp: 'lr 3/11/2010 10:37'! start: aDocument indent := 0. super start: aDocument! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptColumnDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 08:16'! acceptEmptyDocument: aDocument! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptLineDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptNestDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptNestingDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptSequenceDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptTextDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 19:48'! acceptUnionDocument: aDocument self subclassResponsibility! ! !PPFormatter methodsFor: 'visiting' stamp: 'lr 3/11/2010 16:49'! format: aDocument self start: aDocument. ^ stream contents! ! !PPFormatter methodsFor: 'initialization' stamp: 'lr 3/11/2010 10:30'! initialize stream := WriteStream on: (String new: 60)! ! !PPFormatter methodsFor: 'visiting' stamp: 'lr 3/11/2010 10:37'! start: aDocument self visit: aDocument! ! !PPFormatter methodsFor: 'accessing' stamp: 'lr 3/11/2010 09:03'! stream ^ stream! ! !PPFormatter methodsFor: 'accessing' stamp: 'lr 3/11/2010 09:03'! stream: aStream stream := aStream! ! !PPFormatter methodsFor: 'visiting' stamp: 'lr 3/11/2010 08:58'! visit: aDocument aDocument accept: self! ! !PPFormatter methodsFor: 'visiting' stamp: 'lr 3/11/2010 08:25'! visitAll: aCollection aCollection do: [ :each | self visit: each ]! ! PPFormatter subclass: #PPPrettyFormatter instanceVariableNames: 'ribbon width indent column' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Core'! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 11:06'! acceptColumnDocument: aDocument self visit: (aDocument block value: column)! ! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 18:45'! acceptLineDocument: aDocument stream cr; nextPutAll: (String new: (column := indent) withAll: $ )! ! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 17:06'! acceptNestDocument: aDocument indent := indent + aDocument amount. self visit: aDocument document. indent := indent - aDocument amount! ! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 11:06'! acceptNestingDocument: aDocument self visit: (aDocument block value: indent)! ! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 11:58'! acceptSequenceDocument: aDocument self visitAll: aDocument documents! ! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 11:07'! acceptTextDocument: aDocument column := column + aDocument size. stream nextPutAll: aDocument string! ! !PPPrettyFormatter methodsFor: 'visiting-dispatching' stamp: 'lr 3/11/2010 11:19'! acceptUnionDocument: aDocument | available document | available := (width - column) min: (ribbon - column + indent). 1 to: aDocument documents size - 1 do: [ :index | document := aDocument documents at: index. (self fits: document width: available) ifTrue: [ ^ self visit: document ] ]. self visit: aDocument documents last! ! !PPPrettyFormatter methodsFor: 'private' stamp: 'lr 3/11/2010 15:56'! fits: aDocument width: anInteger | string index | string := self copy format: aDocument. index := string indexOf: Character cr ifAbsent: [ string size ]. ^ index <= anInteger! ! !PPPrettyFormatter methodsFor: 'initialization' stamp: 'lr 3/11/2010 15:11'! initialize super initialize. ribbon := 80. width := 120! ! !PPPrettyFormatter methodsFor: 'copying' stamp: 'lr 3/11/2010 10:38'! postCopy super postCopy. stream := WriteStream on: (String new: 60)! ! !PPPrettyFormatter methodsFor: 'accessing' stamp: 'lr 3/11/2010 10:27'! ribbon: anInteger "The width of the ribbon, that is the maximal amount of non-indentation characters on a line." ribbon := anInteger! ! !PPPrettyFormatter methodsFor: 'visiting' stamp: 'lr 3/11/2010 10:08'! start: aDocument indent := column := 0. super start: aDocument! ! !PPPrettyFormatter methodsFor: 'accessing' stamp: 'lr 3/11/2010 10:26'! width: anInteger "The width of the output page." width := anInteger! ! !UndefinedObject methodsFor: '*prettypetit-converting' stamp: 'lr 3/11/2010 15:33'! asDocument ^ PPEmptyDocument new! ! !Collection methodsFor: '*prettypetit' stamp: 'lr 3/11/2010 17:40'! asDocument ^ PPSequenceDocument withAll: (self collect: [ :each | each asDocument ])! ! !Character methodsFor: '*prettypetit-core-converting' stamp: 'lr 3/11/2010 10:17'! asDocument ^ (String with: self) asDocument! ! TestCase subclass: #PPFormatterTests instanceVariableNames: 'document formatter' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Tests'! PPFormatterTests subclass: #PPCompactFormatterTests instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Tests'! !PPCompactFormatterTests methodsFor: 'accessing' stamp: 'lr 3/11/2010 14:36'! formatterClass ^ PPCompactFormatter! ! !PPCompactFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 20:06'! testAlign super testAlign. self assert: document format: 'hi nice\\world'! ! !PPCompactFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:44'! testConcate super testConcate. self assert: document format: '10\\200\\3000\\40000'! ! !PPCompactFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:44'! testConcateFill super testConcateFill. self assert: document format: '10\\200\\3000\\40000'! ! !PPCompactFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:44'! testConcateHorizontal super testConcateHorizontal. self assert: document format: '10200300040000'! ! !PPCompactFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:44'! testConcateVertical super testConcateVertical. self assert: document format: '10\\200\\3000\\40000'! ! !PPCompactFormatterTests methodsFor: 'testing-fillers' stamp: 'lr 3/11/2010 19:49'! testFill super testFill. self assert: document format: 'let empty :: Doc\\nest :: Int -> Doc -> Doc\\linebreak :: Doc'! ! !PPCompactFormatterTests methodsFor: 'testing-fillers' stamp: 'lr 3/11/2010 19:49'! testFillBreak super testFillBreak. self assert: document format: 'let empty :: Doc\\nest :: Int -> Doc -> Doc\\linebreak :: Doc'! ! !PPCompactFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 20:07'! testHang super testHang. self assert: document format: 'the\\hang\\combinator\\indents\\these\\words\\!!'! ! !PPCompactFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 20:08'! testNest super testNest. self assert: document format: ' the\\nest\\combinator\\indents\\these\\words\\!!'! ! !PPCompactFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:45'! testSeparate super testSeparate. self assert: document format: '10\\200\\3000\\40000'! ! !PPCompactFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:45'! testSeparateFill super testSeparateFill. self assert: document format: '10\\200\\3000\\40000'! ! !PPCompactFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:45'! testSeparateHorizontal super testSeparateHorizontal. self assert: document format: '10 200 3000 40000'! ! !PPCompactFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:45'! testSeparateVertical super testSeparateVertical. self assert: document format: '10\\200\\3000\\40000'! ! !PPFormatterTests class methodsFor: 'testing' stamp: 'lr 3/11/2010 14:36'! isAbstract ^ self name = #PPFormatterTests! ! !PPFormatterTests class methodsFor: 'testing' stamp: 'lr 3/11/2010 18:14'! shouldInheritSelectors ^ true! ! !PPFormatterTests methodsFor: 'utilities' stamp: 'lr 3/11/2010 16:50'! assert: aDocument format: aString | expected formatted | expected := aString copyReplaceAll: '\\' with: (String with: Character cr). formatted := formatter stream: String new writeStream; format: aDocument. self assert: expected = formatted description: 'Expected ' , aString printString , ', but got ' , (formatted copyReplaceAll: (String with: Character cr) with: '\\') printString ! ! !PPFormatterTests methodsFor: 'utilities' stamp: 'lr 3/11/2010 16:12'! format: aDocument ^ formatter format: aDocument! ! !PPFormatterTests methodsFor: 'accessing' stamp: 'lr 3/11/2010 16:19'! formatter ^ formatter! ! !PPFormatterTests methodsFor: 'accessing' stamp: 'lr 3/11/2010 14:36'! formatterClass ^ PPFormatter! ! !PPFormatterTests methodsFor: 'running' stamp: 'lr 3/11/2010 16:13'! setUp super setUp. formatter := self formatterClass new! ! !PPFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 16:06'! testAlign document := 'hi' asDocument + ('nice' asDocument \ 'world' asDocument) align! ! !PPFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:34'! testConcate document := #(10 200 3000 40000) asDocument concate! ! !PPFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:34'! testConcateFill document := #(10 200 3000 40000) asDocument concateFill! ! !PPFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:35'! testConcateHorizontal document := #(10 200 3000 40000) asDocument concateHorizontal! ! !PPFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:36'! testConcateVertical document := #(10 200 3000 40000) asDocument concateVertical! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:13'! testEncloseIn document := 'foo' asDocument encloseIn: $x. self assert: document format: 'xfoox'! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:13'! testEncloseInAnd document := 'foo' asDocument encloseIn: $x and: $y. self assert: document format: 'xfooy'! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:13'! testEncloseInAngles document := 'foo' asDocument encloseInAngles. self assert: document format: ''! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:14'! testEncloseInBraces document := 'foo' asDocument encloseInBraces. self assert: document format: '{foo}'! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:14'! testEncloseInBrackets document := 'foo' asDocument encloseInBrackets. self assert: document format: '[foo]'! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:15'! testEncloseInDoubleQuotes document := 'foo' asDocument encloseInDoubleQuotes. self assert: document format: '"foo"'! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:14'! testEncloseInParens document := 'foo' asDocument encloseInParens. self assert: document format: '(foo)'! ! !PPFormatterTests methodsFor: 'testing-enclose' stamp: 'lr 3/11/2010 18:15'! testEncloseInSingleQuotes document := 'foo' asDocument encloseInSingleQuotes. self assert: document format: '''foo'''! ! !PPFormatterTests methodsFor: 'testing-fillers' stamp: 'lr 3/11/2010 19:36'! testFill | items | items := #(('empty' 'Doc') ('nest' 'Int -> Doc -> Doc') ('linebreak' 'Doc')) collect: [ :each | (each first asDocument + '::' + each second asDocument) fill: 6 ]. document := 'let' asDocument + items asDocument concateVertical align! ! !PPFormatterTests methodsFor: 'testing-fillers' stamp: 'lr 3/11/2010 19:54'! testFillBreak | items | items := #(('empty' 'Doc') ('nest' 'Int -> Doc -> Doc') ('linebreak' 'Doc')) collect: [ :each | (each first asDocument + '::' + each second asDocument) fillBreak: 6 ]. document := 'let' asDocument + items asDocument concateVertical align! ! !PPFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 16:23'! testHang document := ('the' asDocument / 'hang' asDocument / 'combinator' asDocument / 'indents' asDocument / 'these' asDocument / 'words' asDocument / '!!' asDocument) hang: 4! ! !PPFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 17:08'! testNest document := ('the' asDocument / 'nest' asDocument / 'combinator' asDocument / 'indents' asDocument / 'these' asDocument / 'words' asDocument / '!!' asDocument) indent: 4! ! !PPFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparate document := #(10 200 3000 40000) asDocument separate! ! !PPFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparateFill document := #(10 200 3000 40000) asDocument separateFill! ! !PPFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparateHorizontal document := #(10 200 3000 40000) asDocument separateHorizontal! ! !PPFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparateVertical document := #(10 200 3000 40000) asDocument separateVertical! ! PPFormatterTests subclass: #PPPrettyFormatterTests instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Tests'! !PPPrettyFormatterTests methodsFor: 'accessing' stamp: 'lr 3/11/2010 14:36'! formatterClass ^ PPPrettyFormatter! ! !PPPrettyFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 16:15'! testAlign super testAlign. self assert: document format: 'hi nice\\ world'! ! !PPPrettyFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:34'! testConcate super testConcate. self assert: document format: '10200300040000'. formatter ribbon: 6; width: 15. self assert: document format: '10\\200\\3000\\40000'! ! !PPPrettyFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:35'! testConcateFill super testConcateFill. self assert: document format: '10200300040000'. formatter ribbon: 4; width: 10. self assert: document format: '10200\\300040000'! ! !PPPrettyFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:35'! testConcateHorizontal super testConcateHorizontal. self assert: document format: '10200300040000'. formatter ribbon: 4; width: 10. self assert: document format: '10200300040000'! ! !PPPrettyFormatterTests methodsFor: 'testing-concate' stamp: 'lr 3/11/2010 19:35'! testConcateVertical super testConcateVertical. self assert: document format: '10\\200\\3000\\40000'. formatter ribbon: 6; width: 15. self assert: document format: '10\\200\\3000\\40000'! ! !PPPrettyFormatterTests methodsFor: 'testing-fillers' stamp: 'lr 3/11/2010 19:36'! testFill super testFill. self assert: document format: 'let empty :: Doc\\ nest :: Int -> Doc -> Doc\\ linebreak :: Doc'! ! !PPPrettyFormatterTests methodsFor: 'testing-fillers' stamp: 'lr 3/11/2010 19:36'! testFillBreak super testFillBreak. self assert: document format: 'let empty :: Doc\\ nest :: Int -> Doc -> Doc\\ linebreak\\ :: Doc'! ! !PPPrettyFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 16:28'! testHang super testHang. self formatter ribbon: 8; width: 20. self assert: document format: 'the hang combinator\\ indents these\\ words !!'! ! !PPPrettyFormatterTests methodsFor: 'testing' stamp: 'lr 3/11/2010 16:28'! testNest super testNest. self formatter ribbon: 8; width: 20. self assert: document format: ' the nest\\ combinator\\ indents these\\ words !!'! ! !PPPrettyFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparate super testSeparate. self assert: document format: '10 200 3000 40000'. formatter ribbon: 6; width: 15. self assert: document format: '10\\200\\3000\\40000'! ! !PPPrettyFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparateFill super testSeparateFill. self assert: document format: '10 200 3000 40000'. formatter ribbon: 6; width: 15. self assert: document format: '10 200\\3000 40000'! ! !PPPrettyFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparateHorizontal super testSeparateHorizontal. self assert: document format: '10 200 3000 40000'. formatter ribbon: 4; width: 10. self assert: document format: '10 200 3000 40000'! ! !PPPrettyFormatterTests methodsFor: 'testing-separate' stamp: 'lr 3/11/2010 19:37'! testSeparateVertical super testSeparateVertical. self assert: document format: '10\\200\\3000\\40000'. formatter ribbon: 6; width: 15. self assert: document format: '10\\200\\3000\\40000'! ! TestCase subclass: #PPPrettyTests instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PrettyPetit-Tests'! !PPPrettyTests class methodsFor: 'accessing' stamp: 'lr 3/11/2010 19:46'! packageNamesUnderTest ^ #('PrettyPetit')! ! !PPPrettyTests methodsFor: 'testing-text' stamp: 'lr 3/11/2010 14:37'! testCharacterText | document | document := $a asDocument. self assert: document string = 'a'. self assert: document size = 1! ! !PPPrettyTests methodsFor: 'testing-sequence' stamp: 'lr 3/11/2010 15:10'! testCommaSequence | document | document := PPSequenceDocument new. document , '1' asDocument. self assert: document documents size = 1. self assert: document documents last string = '1'. document , '2'. self assert: document documents size = 2. self assert: document documents last string = '2'! ! !PPPrettyTests methodsFor: 'testing-sequence' stamp: 'lr 3/11/2010 15:08'! testEmtpySequence | document | document := PPSequenceDocument new. self assert: document documents isEmpty! ! !PPPrettyTests methodsFor: 'testing-text' stamp: 'lr 3/11/2010 14:37'! testIntegerText | document | document := 12 asDocument. self assert: document string = '12'. self assert: document size = 2! ! !PPPrettyTests methodsFor: 'testing-text' stamp: 'lr 3/11/2010 14:37'! testStringText | document | document := 'abc' asDocument. self assert: document string = 'abc'. self assert: document size = 3! ! PPEmptyDocument initialize!