pipes
Ralph Boland
rpboland at gmail.com
Sat Oct 22 20:11:29 UTC 2005
I have a problem-solution that I would like to receive comments on.
Perhaps others
have had similar problem-solutions and can provide me with useful
feedback or even
use my solution. My solution involves creating a subclass of Stream.
My application has a window W onto the contents of a parse tree P.
Currently I convert the parse tree P into text before passing the
text to window W to be displayed. Thus with each
modification of the parse tree P the corresponding complete text
corresponding to P is recomputed.
For my application simple user operations (such as cursor right, input
a single character)
in a different window usually causes significant changes to P requiring
W to be updated. Since this implies completely computing the text corresponding
to P this could be quite slow if P is sufficiently large.
It seems to me that W should only ask for the text that it needs to
display and not all of the text and then only the text that it needs
need be generated.
The cost is then proportional to the size of W rather than the size
of the parse tree P.
To do this I would need a stream S from which W would request text
when it is updated.
S would then get text from the parse tree as required. I think S
should be usable as
much as possible like other streams.
Thus, ideally, I should not need to modify the code that puts the text
corresponding to my parse tree into a stream
nor the code where W currently fetches text from a stream.
I don't however see how this is possible.
It seems that I need to do the following:
1) When stream S is created it must be given a place to send the
data it receives;
that is W or some component of W. S is created by W appropriately.
This is probably done using 2).
2) W has to support a method receiveChar or receiveAttributedChar
and perhaps methods like recieveLineOfText. This method or methods
is passed to S when S is created by W.
This is the ugly part because it totally changes the way W uses
stream S.
Any suggestions on how to avoid (or reduce) this welcome.
3) To update W the parse tree is sent a message like 'P asTextOn:
S' or 'P printOn: S'.
At some point W decides it has all the text it can display and
sends a message
'S stop'. From then on each time S is sent a message such as
'nextPut:'
or 'nextPutAll:' it returns a value such as '0' or nil or
#stoppedPrinting to indicate
that sending it more data is pointless because it will just
discard the data anyway
and not forward the data to W because W doesn't want anymore data.
4) The method asTextOn: (or printOn:) in the classes used to construct P
must be modified to check the result of sending the method. If
P doesn't want
anymore data then they send no more data to P.
Now a call 'P asTextOn: S' requires time proportional to the amount
of text displayed
as desired.
Notes:
1) In fact W is a PluggableTextMorph so that it currently
receives text to be displayed
not as a Stream but as a Collection. I will have to change
PluggableTextMorph
accordingly.
2) The class of S should support methods that allow connecting
its instances together
such as:
S || T || U.
This means that the output of S is sent to the input of T and the
output of T is sent to the input of U where class(T)
and class(U)
are subclasses of class(S) which process their input in some way
before sending the data forward. If the output of U is sent
to W then
'P printOn: S' would send the string representing P to W
to be displayed
but not until the string is processed in some way by S, T,
and U. Since S
currently does nothing it could have been left out.
3) Note 2) strikes me as very useful (like pipes in a Unix shell)
and thus I expect
someone has done this before. In any case, perhaps such a
class or family
of classes like class(S) should be made a standard part of Squeak.
Comments much appreciated. If someone has already done this then code much
appreciated.
Ralph Boland
More information about the Squeak-dev
mailing list
|