'From Squeak3.1alpha of 5 February 2001 [latest update: #3748] on 28 February 2001 at 2:07:35 pm'! "Change Set: syntax9 Date: 28 February 2001 Author: Bob Arning beginnings of ligatures in compound words beginnings of new repeat structure"! UpdatingStringMorph subclass: #SyntaxUpdatingStringMorph instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Tile Scriptors'! !LiteralNode methodsFor: 'tiles' stamp: 'RAA 2/28/2001 13:49'! asMorphicSyntaxIn: parent | row | row _ parent addColumn: #literal on: self. (key isMemberOf: Association) ifFalse: [ row layoutInset: 1. ^ row addMorphBack: (row addString: key storeString special: false)]. key key isNil ifTrue: [ ^ row addTextRow: ('###',key value soleInstance name) ] ifFalse: [ ^ row addTextRow: ('##', key key) ]. ! ! !Player methodsFor: 'misc' stamp: 'RAA 2/28/2001 13:50'! tileReferringToSelf "answer a tile that refers to the receiver" | aTile nn tile | Preferences universalTiles ifTrue: [nn _ self externalName. "name it, if necessary, and put in References" (References includesKey: nn asSymbol) ifFalse: [ References at: nn asSymbol put: self]. tile _ SyntaxMorph new parseNode: (VariableNode new name: nn key: nn code: nil). tile layoutInset: 1; addMorph: (tile addString: nn special: false). tile color: (SyntaxMorph translateColor: #variable). tile extent: tile firstSubmorph extent + (2@2). ^ tile]. aTile _ TileMorph new setObjectRef: nil "disused parm" actualObject: self; typeColor: (ScriptingSystem colorForType: #player). aTile enforceTileColorPolicy. ^ aTile! ! !SyntaxMorph methodsFor: 'initialization' stamp: 'RAA 2/28/2001 10:26'! sample: arg1 "a comment" | temp1 | temp1 _ 5 . (temp1 yourself ). temp1 _ 5 . (temp1 min: arg1 ). self ! ! !SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/28/2001 13:48'! addBlockArg: aMorph "Add a temporary to a block or the method. Return true if succeed" "(aMorph nodeClassIs: TempVariableNode) is known to be true." "***NOTE: This method should be combined with addTempVar:" | tempHolder tt var nn | owner isMethodNode ifTrue: [ ^ (self addTempVar: aMorph)]. "Node for them is not inside the block" "If exists, drop the temp in this block and let use extend it." tt _ self firstSubmorph. tempHolder _ tt firstSubmorph isSyntaxMorph ifTrue: [(tt nodeClassIs: BlockArgsNode) ifTrue: [tt] ifFalse: [nil]] ifFalse: [nil]. nn _ aMorph parseNode key. "name" tempHolder ifNil: ["make whole row" tempHolder _ self addRow: #blockarg1 on: (BlockArgsNode new). self addMorphFront: tempHolder. tempHolder addNoiseString: self noiseBeforeBlockArg. aMorph parseNode name: nn key: nn code: nil. var _ tempHolder addColumn: #tempVariable on: aMorph parseNode. var layoutInset: 1. var addMorphBack: (self addString: nn special: true). self cleanupAfterItDroppedOnMe. ^ true]. tempHolder submorphsDo: [:m | "if present. caller adds the temp as a new line of code to be extended" m isSyntaxMorph and: [m parseNode key = nn ifTrue: [^ false]]]. "If this variable is not present, add it" tempHolder addNoiseString: self noiseBeforeBlockArg. aMorph parseNode name: nn key: nn code: nil. tempHolder addMorphBack: (tempHolder transparentSpacerOfSize: 4@4). var _ tempHolder addColumn: #tempVariable on: aMorph parseNode. var layoutInset: 1. var addMorphBack: (self aSimpleStringMorphWith: nn). var cleanupAfterItDroppedOnMe. ^ true ! ! !SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/28/2001 13:48'! addSingleKeywordRow: aStringLikeItem | row sMorph modifiedString fontToUse | self flag: #emphasis:. "who needs it. who doesn't" (row _ self class row: #text on: nil) borderWidth: 1. modifiedString _ self substituteKeywordFor: aStringLikeItem. sMorph _ self addString: modifiedString special: true. fontToUse _ self fontToUseForSpecialWord: modifiedString. sMorph font: fontToUse "emphasis: 1"; color: (self colorForKeywords: aStringLikeItem and: modifiedString); setProperty: #syntacticallyCorrectContents toValue: aStringLikeItem. row addMorph: sMorph. self addMorphBack: row. ^row! ! !SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/28/2001 13:47'! addString: literalOrVarName special: aBoolean "Create and return an UpdatingStringMorph containing the value. Use an UpdatingStringMorph, so it can inform its owner when it has been edited." ^(self anUpdatingStringMorphWith: literalOrVarName special: aBoolean) target: self; putSelector: #acceptIgnoring:; useStringFormat "keep the getSelector being nil" ! ! !SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/28/2001 13:48'! addTempVar: aMorph "know we are a block inside a MethodNode" "(aMorph nodeClassIs: TempVariableNode) is known to be true." | tempHolder ii tt var nn | tempHolder _ (ii _ owner submorphIndexOf: self) = 1 ifFalse: [tt _ owner submorphs at: ii - 1. (tt isSyntaxMorph and: [tt nodeClassIs: MethodTempsNode]) ifTrue: [tt] ifFalse: [nil]] ifTrue: [nil]. nn _ aMorph parseNode key. "name" tempHolder ifNil: [ tempHolder _ owner addRow: #tempVariable on: MethodTempsNode new. tempHolder addNoiseString: self noiseBeforeBlockArg. owner addMorph: tempHolder inFrontOf: self. aMorph parseNode name: nn key: nn code: nil. aMorph parseNode asMorphicSyntaxIn: tempHolder. tempHolder cleanupAfterItDroppedOnMe. ^ true]. tempHolder submorphsDo: [:m | m isSyntaxMorph and: [m parseNode key = nn ifTrue: [^ false]]]. aMorph parseNode name: nn key: nn code: nil. tempHolder addNoiseString: self noiseBeforeBlockArg. tempHolder addMorphBack: (tempHolder transparentSpacerOfSize: 4@4). var _ tempHolder addColumn: #tempVariable on: aMorph parseNode. var layoutInset: 1. var addMorphBack: (self addString: nn special: true). var cleanupAfterItDroppedOnMe. ^ true! ! !SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/28/2001 13:48'! addTextRow: aStringLikeItem | row | (row _ self class row: #text on: nil) borderWidth: 1. row addMorph: (self addString: (aStringLikeItem copyWithout: Character cr) special: false). self addMorphBack: row. ^row! ! !SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/28/2001 13:48'! addUnaryRow: aStringLikeItem style: aSymbol | row sMorph modifiedString fontToUse | self flag: #emphasis:. "who needs it. who doesn't" (row _ self class row: #text on: nil) borderWidth: 1. modifiedString _ self substituteKeywordFor: aStringLikeItem. sMorph _ self addString: modifiedString special: true. fontToUse _ self fontToUseForSpecialWord: modifiedString. sMorph font: fontToUse emphasis: 1; color: self colorForUnaries; setProperty: #syntacticallyCorrectContents toValue: aStringLikeItem. row addMorph: sMorph. self addMorphBack: row. ^row! ! !SyntaxMorph methodsFor: 'menus' stamp: 'RAA 2/28/2001 14:06'! addMorphBack: m "m setProperty: #howAdded toValue: thisContext longStack." ^super addMorphBack: m! ! !SyntaxMorph methodsFor: 'menus' stamp: 'RAA 2/28/2001 14:00'! addToken: aString type: aColorOrSymbol on: aNode | sMorph modifiedString noiseWord col | self flag: #emphasis:. "who needs it. who doesn't" col _ (self addRow: aColorOrSymbol on: aNode) layoutInset: 1. noiseWord _ [ :w | w ifNotNil: [ col addMorphBack: (self noiseStringMorph: w); addMorphBack: (self tokenVerticalSeparator) ]. ]. self alansTest1 ifTrue: [ (self shouldBeBrokenIntoWords: aColorOrSymbol) ifTrue: [ modifiedString _ self substituteKeywordFor: aString. sMorph _ self addString: modifiedString special: true. sMorph setProperty: #syntacticallyCorrectContents toValue: aString; contents: modifiedString. ] ifFalse: [ sMorph _ self addString: (modifiedString _ aString) special: false. ]. (#(keyword2 upArrow) includes: aColorOrSymbol) ifTrue: [ sMorph font: (self fontToUseForSpecialWord: modifiedString); color: (self colorForKeywords: aString and: modifiedString). ]. (#(keyword2 unary assignmentArrow) includes: aColorOrSymbol) ifTrue: [ sMorph emphasis: 1. ]. aColorOrSymbol == #binary ifTrue: [sMorph color: self colorForBinaries]. aColorOrSymbol == #blockarg1 ifTrue: [ ]. (aColorOrSymbol == #variable or: [aColorOrSymbol == #tempVariable]) ifTrue: [ aString = 'self' ifTrue: [ sMorph setProperty: #wordyVariantOfSelf toValue: true. ]. noiseWord value: (self noiseWordBeforeVariableNode: aNode string: aString). ]. ] ifFalse: [ sMorph _ self addString: aString special: false. ]. col addMorphBack: sMorph. ^col! ! !SyntaxMorph methodsFor: 'menus' stamp: 'RAA 2/28/2001 13:48'! addTokenSpecialCase: aString type: aColorOrSymbol on: aNode | sMorph modifiedString noiseWord col | self flag: #emphasis:. "who needs it. who doesn't" noiseWord _ nil. sMorph _ self addString: aString special: true. self specialBlockFormatting ifTrue: [ (aColorOrSymbol == #keyword2) ifTrue: [ modifiedString _ aString = 'if:' ifTrue: ['Test'] ifFalse: ['Yes']. sMorph font: (self fontToUseForSpecialWord: modifiedString) "emphasis: 1"; color: (self colorForKeywords: aString and: modifiedString); setProperty: #syntacticallyCorrectContents toValue: aString; contents: modifiedString. ]. ]. col _ (self addRow: aColorOrSymbol on: aNode) layoutInset: 1. noiseWord ifNotNil: [ col addMorphBack: (self noiseStringMorph: noiseWord); addMorphBack: (self transparentSpacerOfSize: 3@1) ]. col addMorphBack: sMorph. ^col! ! !SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 10:14'! alanKeywordMessage: aNode isAConditional: template key: key args: args | nodeWithNilReceiver column keywords row onlyOne | (key == #collect: and: [args first isKindOf: BlockNode]) ifTrue: [ ^self alanKwdCollect: aNode isAConditional: template key: key args: args ]. key == #repeatFor:doing: ifTrue: [ ^self alanKwdRepeatForDoing: aNode isAConditional: template key: key args: args ]. key == #if:do: ifTrue: [ ^self alanKwdIfDo: aNode isAConditional: template key: key args: args ]. nodeWithNilReceiver _ aNode copy receiver: nil. template = 1 ifTrue: [ self listDirection: #topToBottom. ]. column _ self addColumn: #keyword1 on: nodeWithNilReceiver. keywords _ key keywords. onlyOne _ args size = 1. keywords with: (args first: keywords size) do: [:kwd :arg | template = 1 ifTrue: [ column addMorphBack: (column transparentSpacerOfSize: 3@3). ]. (row _ column addRow: #keyword2 on: nodeWithNilReceiver) parseNode: (nodeWithNilReceiver as: (onlyOne ifTrue: [MessageNode] ifFalse: [MessagePartNode])); borderColor: row stdBorderColor. template = 1 ifTrue: [row addMorphBack: (row transparentSpacerOfSize: 20@6)]. row addToken: kwd type: #keyword2 on: (onlyOne ifTrue: [SelectorNode new key: kwd code: nil "fill this in?"] ifFalse: [KeyWordNode new]). (arg asMorphicSyntaxIn: row) setConditionalPartStyle. ]. onlyOne ifTrue: [ self replaceSubmorph: column by: row. column _ row. ]. ! ! !SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 10:09'! alanKwdCollect: aNode isAConditional: template key: key args: args | nodeWithNilReceiver row kwdHolder | nodeWithNilReceiver _ aNode copy receiver: nil. (row _ self addRow: #keyword2 on: nodeWithNilReceiver) borderWidth: 1; parseNode: (nodeWithNilReceiver as: MessageNode); borderColor: row stdBorderColor. kwdHolder _ row addToken: key type: #keyword2 on: (SelectorNode new key: key code: nil "fill this in?"). kwdHolder firstSubmorph setProperty: #syntacticallyCorrectContents toValue: key asString; contents: ''. args first asMorphicCollectSyntaxIn: row. "row setSpecialOuterTestFormat." ! ! !SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 10:08'! alanKwdIfDo: aNode isAConditional: template key: key args: args | nodeWithNilReceiver column keywords row | nodeWithNilReceiver _ aNode copy receiver: nil. column _ self addColumn: #keyword1 on: nodeWithNilReceiver. keywords _ key keywords. keywords with: (args first: keywords size) do: [:kwd :arg | (row _ column addRow: #keyword2 on: nodeWithNilReceiver) parseNode: (nodeWithNilReceiver as: MessagePartNode). kwd = 'do:' ifTrue: [ row addMorphBack: (row transparentSpacerOfSize: 26@6). ] ifFalse: [ row addMorphBack: (row transparentSpacerOfSize: 10@6). ]. row addTokenSpecialCase: kwd type: #keyword2 on: KeyWordNode new. (arg asMorphicSyntaxIn: row) setConditionalPartStyle. ]. ! ! !SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 10:16'! alanKwdRepeatForDoing: aNode isAConditional: template key: key args: args | nodeWithNilReceiver row column keywords | nodeWithNilReceiver _ aNode copy receiver: nil. column _ self addColumn: #keyword1 on: nodeWithNilReceiver. keywords _ key keywords. keywords with: (args first: keywords size) do: [:kwd :arg | (row _ column addRow: #keyword2 on: nodeWithNilReceiver) parseNode: (nodeWithNilReceiver as: MessagePartNode). row addToken: kwd type: #keyword2 on: KeyWordNode new. (arg asMorphicSyntaxIn: row) setConditionalPartStyle. ]. ! ! !SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 13:48'! alansMessageNode: aNode receiver: receiver selector: selector keywords: key arguments: args | row receiverMorph testAndReceiver anotherSelf wordyMorph template | template _ self alansTemplateStyleFor: key. receiver ifNotNil: ["i.e. not a cascade" anotherSelf _ self constructSelfVariant: receiver and: key. anotherSelf ifNotNil: [ wordyMorph _ self addString: anotherSelf special: true. wordyMorph setProperty: #wordyVariantOfSelf toValue: true. self addMorph: wordyMorph. self layoutInset: 1. ^self ]. testAndReceiver _ self. template = 1 ifTrue: [ testAndReceiver _ self addRow: #keyword1 on: nil. self setSpecialOuterTestFormat. testAndReceiver addNoiseString: 'Test' ]. false "template = 2" ifTrue: [ testAndReceiver _ self addRow: #keyword1 on: nil. "self setSpecialOuterTestFormat." testAndReceiver addNoiseString: 'Repeat for' ]. receiverMorph _ receiver asMorphicSyntaxIn: testAndReceiver. template = 1 ifTrue: [receiverMorph setConditionalPartStyle]. ]. "unary messages" args size = 0 ifTrue: [ ((receiverMorph notNil) and: [receiverMorph nodeClassIs: MessageNode]) ifTrue: [ self addMorphBack: self tokenVerticalSeparator ]. row _ (self addUnaryRow: key style: #unary) layoutInset: 1. ^ row parseNode: selector ]. "binary messages" key last = $: ifFalse: [ ^self alanBinaryPostRcvr: aNode key: key args: args ]. "keyword messages" receiverMorph ifNotNil: [receiverMorph setConditionalPartStyle]. self setSpecialOuterTestFormat. self alanKeywordMessage: aNode isAConditional: template key: key args: args! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 13:46'! anUpdatingStringMorphWith: aString special: aBoolean self alansTest1 ifTrue: [ ^(aBoolean ifTrue: [SyntaxUpdatingStringMorph] ifFalse: [UpdatingStringMorph]) contents: aString font: self alansCurrentFontPreference ]. ^UpdatingStringMorph contents: aString! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 09:35'! lighterColor ^Color gray: 0.9 "(Color r: 0.935 g: 0.935 b: 0.935)" "paleGreen lighter" ! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 13:42'! shouldBeBrokenIntoWords: aSymbol ^#(methodHeader1 methodHeader1 keyword2 upArrow tempVariable tempVariableDeclaration blockarg2 variable) includes: aSymbol! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 14:06'! substituteKeywordFor: aString aString isEmpty ifTrue: [^aString asString]. aString asString = '^ ' ifTrue: [^'answer']. aString asString = 'ifTrue:' ifTrue: [^'Yes']. aString asString = 'ifFalse:' ifTrue: [^'No']. aString asString = 'self' ifTrue: [^'self']. aString first isUppercase ifTrue: [^aString asString]. ^String streamContents: [ :strm | aString do: [ :each | each = $: ifFalse: [ each isUppercase ifTrue: [strm space; nextPut: each asLowercase] ifFalse: [strm nextPut: each] ]. ] ].! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 12:46'! tokenVerticalSeparator ^self tokenVerticalSeparatorBlueBar ! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 12:45'! tokenVerticalSeparatorBlueBar ^RectangleMorph new vResizing: #spaceFill; setProperty: #tokenVerticalSeparator toValue: #true; extent: 3@15; borderWidth: 1; borderColor: Color transparent; color: (Color r: 0.581 g: 0.774 b: 0.903)! ! !SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 12:45'! tokenVerticalSeparatorGray | outer inner | outer _ AlignmentMorph newColumn vResizing: #spaceFill; setProperty: #tokenVerticalSeparator toValue: #true; listCentering: #center; cellPositioning: #center; extent: 3@15; borderWidth: 0; color: (Color transparent). inner _ RectangleMorph new setProperty: #tokenVerticalSeparator toValue: #true; extent: 3@3; cellPositioning: #center; borderWidth: 0; color: (Color black alpha: 0.3). outer addMorph: inner. ^outer! ! !SyntaxTestMethods methodsFor: 'as yet unclassified' stamp: 'RAA 2/28/2001 09:52'! repeatExample self repeatFor: (1 to: 50) doing: [ :i | i + 3]! ! !SyntaxUpdatingStringMorph methodsFor: 'as yet unclassified' stamp: 'RAA 2/28/2001 13:35'! drawOn: aCanvas | tempForm scanner strm where chars wid spaceWidth putLigature topOfLigature sizeOfLigature colorOfLigature dots | tempForm _ Form extent: self extent depth: aCanvas depth. scanner _ DisplayScanner quickPrintOn: tempForm box: tempForm boundingBox font: self fontToUse. spaceWidth _ scanner stringWidth: ' '. strm _ ReadStream on: contents. where _ 0@0. topOfLigature _ self height // 2 - 1. sizeOfLigature _ (spaceWidth-2)@(spaceWidth-2). colorOfLigature _ Color black alpha: 0.3 "veryLightGray". dots _ OrderedCollection new. putLigature _ [ dots add: ((where x + 1) @ topOfLigature extent: sizeOfLigature). where _ where + (spaceWidth@0). ]. [strm atEnd] whileFalse: [ [strm peek = $ ] whileTrue: [ strm next. putLigature value. ]. chars _ strm upTo: $ . wid _ scanner stringWidth: chars. scanner drawString: chars at: where. where _ where + (wid@0). strm atEnd ifFalse: [putLigature value]. ]. aCanvas paintImage: tempForm at: self topLeft. dots do: [ :each | aCanvas fillRectangle: (each translateBy: self topLeft) fillStyle: colorOfLigature. ]. ! ! SyntaxMorph removeSelector: #addString:! SyntaxMorph removeSelector: #alanKeywordMessageCollect:isAConditional:key:args:! SyntaxMorph removeSelector: #anUpdatingStringMorphWith:! SyntaxMorph removeSelector: #tokenVerticalSeparator1!