<br><br><div class="gmail_quote">On Fri, Feb 18, 2011 at 1:41 PM, Igor Stasenko <span dir="ltr">&lt;<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
It seems that you guys (Stephane &amp; Juan) both making same mistake. :)<br>
<br>
You trying to assign multiple different roles to Transcript at once:<br>
 - be a stream<br>
 - be a GUI element (can draw/update itself on a screen)..<br>
<br>
Hey.. Transcript is not a swiss knife!<br>
It is just a stream (kind of special one), but other than that.. it is<br>
just a stream.<br>
And what you see on a screen - it is just a view of it.<br></blockquote><div><br></div><div>+1</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
So, Juan it is cool that you have better Transcript... still it having<br>
same deficiencies which i shown to Stephane not long ago,<br>
and tried to convince him that Transcript is a stream, not a window. A<br>
Transcript window is just a view of real transcript.<br>
<br>
And i think this is quite easy to make this separation and have sound model.<br>
<div><div></div><div class="h5"><br>
<br>
On 18 February 2011 19:33, Juan Vuletich &lt;<a href="mailto:juan@jvuletich.org">juan@jvuletich.org</a>&gt; wrote:<br>
&gt; Hi Eliot,<br>
&gt;<br>
&gt; Eliot Miranda wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi John,<br>
&gt;&gt;<br>
&gt;&gt;    good questions.<br>
&gt;&gt;<br>
&gt;&gt; On Thu, Feb 17, 2011 at 6:21 AM, John B Thiel &lt;<a href="mailto:jbthiel@gmail.com">jbthiel@gmail.com</a><br>
&gt;&gt; &lt;mailto:<a href="mailto:jbthiel@gmail.com">jbthiel@gmail.com</a>&gt;&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;    Cog VM -- Thanks and Performance / Optimization Questions<br>
&gt;&gt;<br>
&gt;&gt;    ...<br>
&gt;&gt;    (Also, any notoriously slow subsystems?  For example, Transcript<br>
&gt;&gt;    writing is glacial.)<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Someone should replace the Transcript&#39;s reliance on (I think) some kind of<br>
&gt;&gt; FormMorph which moved huge numbers of bits on each write.  But this is not a<br>
&gt;&gt; VM issue.  It&#39;s a Smalltalk issue.  Whoever did this would instantly become<br>
&gt;&gt; a hero.<br>
&gt;<br>
&gt; There are other problems with Transcript besides performance. It is easy to<br>
&gt; break the UI if called at the wrong times. In those cases, it is usually<br>
&gt; needed to kill Squeak from the OS. Besides, it is not thread safe.<br>
&gt;<br>
&gt; Instantly becoming a hero sounds cool, so this is my attempt at it :) I only<br>
&gt; tried this in Cuis, but I believe it should work on Squeak and Pharo without<br>
&gt; much trouble. After loading this code, you can evaluate &#39;Smalltalk at:<br>
&gt; #Transcript put: NewTranscript&#39;.<br>
&gt;<br>
&gt; Some good properties of this are:<br>
&gt; - Very fast.<br>
&gt; - Thread safe!<br>
&gt; - Doesn&#39;t use Morphic at all. Can be used to debug Morphic itself.<br>
&gt; - Doesn&#39;t do delayed execution (no events, no forked processes). Immediate<br>
&gt; visual feedback.<br>
&gt; - Can show itself on Display, log to File, both, or none.<br>
&gt; - Can be used for headless or remote images (for example, web servers).<br>
&gt;<br>
&gt; Some possible downsides are:<br>
&gt; - Output only. Not a text editor. We have the Workspace and the Transcripter<br>
&gt; for that.<br>
&gt; - No seamless Morphic integration. I&#39;ll do one for Cuis, though.<br>
&gt;<br>
&gt; If no serious problems are found, I&#39;ll remove TranscriptStream from Cuis,<br>
&gt; and rename this class as Transcript.<br>
&gt;<br>
&gt; Cheers,<br>
&gt; Juan Vuletich<br>
&gt;<br>
</div></div>&gt; &#39;From Cuis 3.0 of 31 January 2011 [latest update: #790] on 18 February 2011<br>
&gt; at 2:36:31 pm&#39;!<br>
&gt; !classDefinition: #NewTranscript category: #&#39;System-Support&#39;!<br>
&gt; Object subclass: #NewTranscript<br>
&gt;        instanceVariableNames: &#39;&#39;<br>
&gt;        classVariableNames: &#39;&#39;<br>
&gt;        poolDictionaries: &#39;&#39;<br>
&gt;        category: &#39;System-Support&#39;!<br>
&gt;<br>
&gt; !NewTranscript commentStamp: &#39;&lt;historical&gt;&#39; prior: 0!<br>
&gt; A new implementation of Transcript.<br>
&gt; - Thread safe.<br>
&gt; - Very fast.<br>
&gt; - Independent of Morphic or any other UI framework.<br>
&gt; - Inmediate feedback.<br>
&gt; - Can log to file.<br>
&gt; - Not an editor. Only used for output.<br>
&gt; - All protocol is on the Class side!<br>
&gt;<br>
&gt; !classDefinition: &#39;NewTranscript class&#39; category: nil!<br>
&gt; NewTranscript class<br>
&gt;        instanceVariableNames: &#39;entries firstIndex lastIndex accessSemaphore<br>
&gt; unfinishedEntry logToFile showOnDisplay innerRectangle lastDisplayTime&#39;!<br>
&gt;<br>
&gt; !DateAndTime methodsFor: &#39;squeak protocol&#39; stamp: &#39;jmv 2/18/2011 12:57&#39;!<br>
&gt; printWithMsOn: aStream<br>
&gt;        &quot;Print with millisecond resolution, no leading space, no offset.&quot;<br>
&gt;<br>
&gt;        | ps |<br>
&gt;        self printYMDOn: aStream withLeadingSpace: false.<br>
&gt;        aStream nextPut: $T.<br>
&gt;        self printHMSOn: aStream.<br>
&gt;        ps _ (self nanoSecond // 1000000) printString padded: #left to: 3<br>
&gt; with: $0.<br>
&gt;        aStream nextPut: $..<br>
&gt;        aStream nextPutAll: ps! !<br>
&gt;<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;preferred protocol&#39; stamp: &#39;jmv 2/18/2011<br>
&gt; 14:16&#39;!<br>
&gt; clear<br>
&gt;        | stream |<br>
&gt;        accessSemaphore critical: [<br>
&gt;                &quot;Having at least one entry simplifies handling of the entries<br>
&gt; circular collection&quot;<br>
&gt;                firstIndex _ 1.<br>
&gt;                lastIndex _ 1.<br>
&gt;                entries at: 1 put: &#39;Transcript&#39;.<br>
&gt;                unfinishedEntry reset.<br>
&gt;<br>
&gt;                logToFile ifTrue: [<br>
&gt;                        stream _ StandardFileStream forceNewFileNamed: self<br>
&gt; filename.<br>
&gt;                        [<br>
&gt;                                stream nextPutAll: &#39;Transcript log started:<br>
&gt; &#39;.<br>
&gt;                                DateAndTime now printOn: stream.<br>
&gt;                                stream<br>
&gt;                                        lf;<br>
&gt;                                        nextPutAll:<br>
&gt; &#39;------------------------------------------------------------------------&#39;;<br>
&gt;                                        lf<br>
&gt;                        ] ensure: [ stream close ]]].<br>
&gt;        self display! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;preferred protocol&#39; stamp: &#39;jmv 2/18/2011<br>
&gt; 14:16&#39;!<br>
&gt; log: aString<br>
&gt;        self addEntry: aString.<br>
&gt;        self display! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;preferred protocol&#39; stamp: &#39;jmv 2/18/2011<br>
&gt; 11:49&#39;!<br>
&gt; logToFile<br>
&gt;        &quot;<br>
&gt;        self logToFile<br>
&gt;        &quot;<br>
&gt;        logToFile _ true! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:20&#39;!<br>
&gt; cr<br>
&gt;        &quot;WriteStream protocol.<br>
&gt;        In the older TranscriptStream, it added a CR character.<br>
&gt;        Now, finish the current incomplete entry.&quot;<br>
&gt;<br>
&gt;        self finishEntry! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:20&#39;!<br>
&gt; crtab<br>
&gt;        &quot;WriteStream protocol.<br>
&gt;        End the current entry, and start a new one starting with a single tab<br>
&gt; character.&quot;<br>
&gt;<br>
&gt;        self cr; tab! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:21&#39;!<br>
&gt; endEntry<br>
&gt;        &quot;For compatibility with old TranscriptStream. nop here&quot;! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:21&#39;!<br>
&gt; flush<br>
&gt;        &quot;For compatibility with old TranscriptStream. nop here&quot;! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 14:17&#39;!<br>
&gt; nextPut: aCharacter<br>
&gt;        &quot;WriteStream protocol.<br>
&gt;        Append aCharacter to the unfinishedEntry.<br>
&gt;        cr characters sent with this message do NOT finish the current<br>
&gt; unfinishedEntry.&quot;<br>
&gt;<br>
&gt;        unfinishedEntry nextPut: aCharacter.<br>
&gt;        self displayUnfinishedEntry! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 14:17&#39;!<br>
&gt; nextPutAll: aString<br>
&gt;        &quot;WriteStream protocol.<br>
&gt;        Append aString to the unfinishedEntry.<br>
&gt;        cr characters sent with this message do NOT finish the current<br>
&gt; unfinishedEntry.&quot;<br>
&gt;<br>
&gt;        unfinishedEntry nextPutAll: aString.<br>
&gt;        self displayUnfinishedEntry! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:20&#39;!<br>
&gt; print: anObject<br>
&gt;        &quot;Stream protocol&quot;<br>
&gt;        anObject printOn: self! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:22&#39;!<br>
&gt; show: anObject<br>
&gt;        &quot;Old TranscriptStream protocol.&quot;<br>
&gt;        self nextPutAll: anObject asString! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:22&#39;!<br>
&gt; space<br>
&gt;        &quot;WriteStream protocol.<br>
&gt;        Append a space character to the receiver.&quot;<br>
&gt;<br>
&gt;        self nextPut: Character space! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;old Transcript compatibility&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 11:22&#39;!<br>
&gt; tab<br>
&gt;        &quot;WriteStream protocol.<br>
&gt;        Append a tab character to the receiver.&quot;<br>
&gt;<br>
&gt;        self nextPut: Character tab! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;private&#39; stamp: &#39;jmv 2/18/2011 12:59&#39;!<br>
&gt; addEntry: aString<br>
&gt;        &quot;Add a new entrie to the entries circular list. If full, a new entry<br>
&gt; will replace the oldest one.&quot;<br>
&gt;        | msg now |<br>
&gt;        logToFile ifTrue: [<br>
&gt;                now _ DateAndTime now.<br>
&gt;                msg _ String streamContents: [ :strm |<br>
&gt;                        now printWithMsOn: strm.<br>
&gt;                        strm<br>
&gt;                                nextPutAll: &#39; process:&#39;;<br>
&gt;                                nextPutAll: Processor activeProcess priority<br>
&gt; printString;<br>
&gt;                                nextPut: $ ;<br>
&gt;                                nextPutAll: Processor activeProcess hash<br>
&gt; printString;<br>
&gt;                                nextPut: $ ;<br>
&gt;                                nextPutAll: aString;<br>
&gt;                                lf ]].<br>
&gt;<br>
&gt;        self addEntry: aString logToFile: msg! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;private&#39; stamp: &#39;jmv 2/18/2011 12:34&#39;!<br>
&gt; addEntry: aString logToFile: otherString<br>
&gt;        &quot;Add a new entrie to the entries circular list. If full, a new entry<br>
&gt; will replace the oldest one.&quot;<br>
&gt;        | stream |<br>
&gt;        accessSemaphore critical: [<br>
&gt;<br>
&gt;                &quot;Internal circular collection&quot;<br>
&gt;                lastIndex _ lastIndex \\ self maxEntries + 1.<br>
&gt;                firstIndex = lastIndex ifTrue: [<br>
&gt;                        firstIndex _ firstIndex \\ self maxEntries + 1 ].<br>
&gt;                entries at: lastIndex put: aString.<br>
&gt;<br>
&gt;                &quot;external file&quot;<br>
&gt;                otherString ifNotNil: [<br>
&gt;                        [<br>
&gt;                                stream _ StandardFileStream fileNamed: self<br>
&gt; filename.<br>
&gt;                                stream<br>
&gt;                                        setToEnd;<br>
&gt;                                        nextPutAll: otherString;<br>
&gt;                                        flush]<br>
&gt;                        ensure: [ stream close ]<br>
&gt;                ]<br>
&gt;        ]! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;private&#39; stamp: &#39;jmv 2/18/2011 14:16&#39;!<br>
&gt; finishEntry<br>
&gt;        | newEntry |<br>
&gt;        newEntry _ unfinishedEntry contents.<br>
&gt;        unfinishedEntry reset.<br>
&gt;        self addEntry: newEntry.<br>
&gt;        self display! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;displaying&#39; stamp: &#39;jmv 2/18/2011 14:20&#39;!<br>
&gt; display<br>
&gt;        showOnDisplay ifTrue: [<br>
&gt;                self displayOn: Display.<br>
&gt;                lastDisplayTime _ DateAndTime now ]! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;displaying&#39; stamp: &#39;jmv 2/18/2011 14:09&#39;!<br>
&gt; displayOn: aForm<br>
&gt;        &quot;<br>
&gt;        experimentos<br>
&gt;        NewTranscript displayOn: Display<br>
&gt;        &quot;<br>
&gt;        | font port count i string x y fh f |<br>
&gt;        aForm border: (innerRectangle outsetBy: 3) width: 3.<br>
&gt;        aForm fill: innerRectangle fillColor: Color white.<br>
&gt;        port _ BitBlt toForm: aForm.<br>
&gt;        port clipWidth: innerRectangle right.<br>
&gt;        font _ StrikeFont default.<br>
&gt;        font installOn: port foregroundColor: Color black.<br>
&gt;<br>
&gt;        fh _ font height.<br>
&gt;        count _ innerRectangle height // fh-1.<br>
&gt;        x _ innerRectangle left.<br>
&gt;        y _ innerRectangle top.<br>
&gt;        f _ firstIndex-1.<br>
&gt;        firstIndex &gt; lastIndex ifTrue: [ f _ f - self maxEntries ].<br>
&gt;        i _ (lastIndex - count max: f) \\ self maxEntries + 1.<br>
&gt;        [<br>
&gt;                string _ entries at: i.<br>
&gt;                port displayString: string from: 1 to: string size at: x@y<br>
&gt; strikeFont: font kern: font baseKern negated.<br>
&gt;                y _ y + fh.<br>
&gt;                i = lastIndex<br>
&gt;        ] whileFalse: [ i _ i \\ self maxEntries + 1 ].<br>
&gt;<br>
&gt;        string _ unfinishedEntry contents.<br>
&gt;        port displayString: string from: 1 to: string size at: x@y<br>
&gt; strikeFont: font kern: font baseKern negated.! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;displaying&#39; stamp: &#39;jmv 2/18/2011 14:23&#39;!<br>
&gt; displayUnfinishedEntry<br>
&gt;        showOnDisplay ifTrue: [<br>
&gt;                (lastDisplayTime isNil or: [ (DateAndTime now -<br>
&gt; lastDisplayTime) totalSeconds &gt; 1 ])<br>
&gt;                        ifTrue: [ ^self display ].<br>
&gt;                self displayUnfinishedEntryOn: Display ]! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;displaying&#39; stamp: &#39;jmv 2/18/2011 14:14&#39;!<br>
&gt; displayUnfinishedEntryOn: aForm<br>
&gt;<br>
&gt;        | font port count string x y fh |<br>
&gt;        port _ BitBlt toForm: aForm.<br>
&gt;        port clipWidth: innerRectangle right.<br>
&gt;        font _ StrikeFont default.<br>
&gt;        font installOn: port foregroundColor: Color black.<br>
&gt;<br>
&gt;        fh _ font height.<br>
&gt;        count _ innerRectangle height // fh-1.<br>
&gt;        x _ innerRectangle left.<br>
&gt;<br>
&gt;        string _ unfinishedEntry contents.<br>
&gt;        y _ ((lastIndex - firstIndex \\ self maxEntries) min: count-1) + 1 *<br>
&gt; font height + innerRectangle top.<br>
&gt;        port displayString: string from: 1 to: string size at: x@y<br>
&gt; strikeFont: font kern: font baseKern negated.! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;class initialization&#39; stamp: &#39;jmv<br>
&gt; 2/18/2011 13:13&#39;!<br>
&gt; initialize<br>
&gt;        &quot;<br>
&gt;        self initialize<br>
&gt;        &quot;<br>
&gt;        showOnDisplay _ true.<br>
&gt;        innerRectangle _ 20@20 extent: 300@500.<br>
&gt;        logToFile _ false.<br>
&gt;        entries _ Array new: self maxEntries.<br>
&gt;        unfinishedEntry _ &#39;&#39; writeStream.<br>
&gt;        accessSemaphore _ Semaphore forMutualExclusion.<br>
&gt;        self clear! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;constants&#39; stamp: &#39;jmv 2/18/2011 12:33&#39;!<br>
&gt; filename<br>
&gt;        ^&#39;transcript.txt&#39;! !<br>
&gt;<br>
&gt; !NewTranscript class methodsFor: &#39;constants&#39; stamp: &#39;jmv 2/18/2011 12:59&#39;!<br>
&gt; maxEntries<br>
&gt;        ^1000! !<br>
&gt;<br>
&gt; NewTranscript initialize!<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
<font color="#888888"><br>
<br>
<br>
--<br>
Best regards,<br>
Igor Stasenko AKA sig.<br>
</font></blockquote></div><br>