[squeak-dev] The Inbox: Collections-eem.732.mcz

Eliot Miranda eliot.miranda at gmail.com
Thu Feb 9 17:26:17 UTC 2017


On Wed, Feb 8, 2017 at 12:47 PM, Tobias Pape <Das.Linux at gmx.de> wrote:

>
> On 08.02.2017, at 19:59, Eliot Miranda <eliot.miranda at gmail.com> wrote:
>
> > Hi All,
> >
> >     I'd really like this to be in trunk.  I've just written a blog post
> in a Workspace using this code (http://www.mirandabanda.org/
> cogblog/2017/02/07/smalltalk-scanning-and-shcontrol-structures/) and it
> turns creating a blog post into a simple copyHtml paste operation from a
> workspace to (in my case) WordPress.  So any reviewers?
>
> Care to explain it a litte bit? :)
>

Here's a screen shot of a workspace from which I used the inbox version of
copyHtml to produce the blog post.


​
Compare it against
http://www.mirandabanda.org/cogblog/2017/02/07/smalltalk-scanning-and-shcontrol-structures/;
it's a pretty good mapping.


It looks a bit complicated to my eyes.
> Also, do you really want <pre>? (http://stackoverflow.com/
> questions/4611591/code-vs-pre-vs-samp-for-inline-and-block-
> code-snippets#4611735)
>


​
The thing to note is that normal text isn't indented, and presentation text
is.  HTML rendering in browsers doesn't preserve indentation if one uses
<blockquote>, but does if one uses <pre>.  Using <code> preserves
indentation but can include ugly sidebars.  So <pre></pre> is definitely
the tag to use to include indented text.  Indented text may /not/ be code,
but we clearly want it to be indented correctly.  Basically, all the change
does is enclose a run of indented lines in <pre></pre>, which will preserve
indentation and not introduce unwanted artifacts such as included using the
<code> tag, so this should be uncontroversial.

Do do this, scanning of the text needs to be modified to spot indentations
at the beginning of lines.  To do that I
introduce HtmlReadWriter>>#linesWithAttributesIn:do: to sit above
RunArray>>withStartStopAndValueDo: and ensure that the block argument to
linesWithAttributesIn:do: is only ever supplied with strings that, if they
contain a carriage return, have the carriage return at the end.  This makes
it easy for HtmlReadWriter>>#nextPutText: to spot f it is at the beginning
of a line, and therefore to know if it is processing a line within a run of
indented text.  So here's the method:

*nextPutText:* aText

    | atStartOfLine inIndent cr |    atStartOfLine *:=* true.
inIndent *:=* false.    cr *:=* Character cr.    self
linesWithAttributesIn: aText do:        [:subString :attributes | |
indented |        atStartOfLine ifTrue:            [indented *:=*
subString first == Character tab.             indented ~~ inIndent
ifTrue:                [stream nextPutAll: (indented ifTrue: ['<pre>']
ifFalse: ['</pre>']).                 inIndent *:=* indented]].
attributes do: [:each | self writeStartTagFor: each].        inIndent
          ifTrue: [self writePresentationContent: subString]
 ifFalse: [self writeContent: subString].        attributes reverseDo:
[:each | self writeEndTagFor: each].        atStartOfLine *:=*
subString last == cr].    inIndent ifTrue:        [stream nextPutAll:
'</pre>']

So if atStartOfLine, we need to check for indentation (line begins
with a tab).  If at this pint there is a change from non-indenting to
indenting, or vice verse, we need to add either a <pre> or a </pre>
tag.  While processing indented text we shouldn't map carriage return
to <br> because that will give us a double line feed, and so if
indenting we process using writePresentationContent: which is the same
as writeContent: except for the carriage return -> <br> processing.
The block spots being atStartOfLine by looking at the last character
of the string, which linesWithAttributesIn:do: guarantees is the only
place a carriage return will occur in the block.  Finally at the end
of the method if indenting we close off the indentation by generating
the matching </pre>.



> The HtmlReadWriter seems to (up until now) pretty directly map text
> attributes to html attributes.
>

But because it does't enclose indented text in <pre></pre> it causes
browsers to screw up indented text, and requires lots of painful hand
editing to correct.  I fixed copyHtml to avoid this.

You seem to want to differentiate code from non-code, so what about having
> a do-it attribute, that does exactly that?
>

Not really.  I just want to preserve indentation.  Code is merely one kind
of text for which indentation is important.  But indented lists are valid
also.  I don't think one should be introducing markup into the Workspace.
Instead I think copyHtml should be trying to construct HTML that is
visually equivalent to the source text.  My modifications achieve that.  I
don't like the idea of adding a do-it attribute.  I don't see the need.
The modifications I introduce do it automatically.  Compare the workspace
above with my blog post.


Because now, there's also no back-reading of such html into a Text object,
> wich I find unfortunate.
> I think, the readwriter should be able to read what it has written.
>
> I know, it's a mere convenience thing, but still, its very procedural, and
> seeing #~~ in high-level code is strange to my eyes…
>
> What would be really cool is to
>         - mark the code as do-it
>         - have the do-it present itself as <code> or <pre> on Html.
>

I disagree.  All that is needed is to use <pre></pre> correctly.


>
> Btw: there's also an TextIndent attribute that we could leverage.
>

Perhaps.


>
> Best regards
>         -Tobias
>


BTW, Marcel, if one uses TAB or SHIFT-TAB to change the indentation of
colored text, the operation strips the colouration :-(


> >
> > On Wed, Feb 8, 2017 at 10:55 AM, <commits at source.squeak.org> wrote:
> > Eliot Miranda uploaded a new version of Collections to project The Inbox:
> > http://source.squeak.org/inbox/Collections-eem.732.mcz
> >
> > ==================== Summary ====================
> >
> > Name: Collections-eem.732
> > Author: eem
> > Time: 8 February 2017, 10:55:41.894202 am
> > UUID: c2c7f1c4-f586-4872-b2c7-6fb7f9cd6527
> > Ancestors: Collections-dtl.731
> >
> > Modify HtmlReadWriter to enclose indented text within <pre></pre> to
> preserve formatting of, for example, code.
> >
> > =============== Diff against Collections-dtl.731 ===============
> >
> > Item was added:
> > + ----- Method: HtmlReadWriter>>linesWithAttributesIn:do: (in category
> 'writing') -----
> > + linesWithAttributesIn: aText do: aBlock
> > +       "Evauate aBlock with a string and the emphasis for that string,
> guaranteeing
> > +        that if the string contains a line break, it occurs at the end
> of the line."
> > +       aText runs withStartStopAndValueDo:
> > +               [:start :stop :attributes | | att idx startIdx |
> > +                startIdx := start.
> > +                [att := aText attributesAt: startIdx.
> > +                 idx := aText string indexOf: Character cr from:
> startIdx to: stop ifAbsent: stop.
> > +                 aBlock value: (aText string copyFrom: startIdx to:
> idx) value: att.
> > +                 idx < stop]
> > +                       whileTrue:
> > +                               [startIdx := idx + 1]]!
> >
> > Item was changed:
> >   ----- Method: HtmlReadWriter>>nextPutText: (in category 'accessing')
> -----
> >   nextPutText: aText
> > +       | atStartOfLine inIndent cr |
> > +       atStartOfLine := true.
> > +       inIndent := false.
> > +       cr := Character cr.
> > +       self linesWithAttributesIn: aText do:
> > +               [:string :attributes | | indented |
> > +               atStartOfLine ifTrue:
> > +                       [indented := string first == Character tab.
> > +                        indented ~~ inIndent ifTrue:
> > +                               [stream nextPutAll: (indented ifTrue:
> ['<pre>'] ifFalse: ['</pre>']).
> > +                                inIndent := indented]].
> > +               attributes do: [:each | self writeStartTagFor: each].
> > +               inIndent
> > +                       ifTrue: [self writePresentationContent: string]
> > +                       ifFalse: [self writeContent: string].
> > +               attributes reverseDo: [:each | self writeEndTagFor:
> each].
> > +               atStartOfLine := string last == cr].
> > +       inIndent ifTrue:
> > +               [stream nextPutAll: '</pre>']!
> > -
> > -       aText runs
> > -               withStartStopAndValueDo: [:start :stop :attributes |
> > -                       | att str |
> > -                       att := aText attributesAt: start.
> > -                       str := aText string copyFrom: start to: stop.
> > -
> > -                       att do: [:each | self writeStartTagFor: each].
> > -                       self writeContent: str.
> > -                       att reverse do: [:each | self writeEndTagFor:
> each]]!
> >
> > Item was added:
> > + ----- Method: HtmlReadWriter>>writePresentationContent: (in category
> 'writing') -----
> > + writePresentationContent: aString
> > +
> > +       aString do: [:char |
> > +               char = Character tab
> > +                       ifTrue: [stream nextPutAll:
> '    ']
> > +                       ifFalse: [(String htmlEntities keyAtValue: char
> ifAbsent: [])
> > +                               ifNil: [stream nextPut: char]
> > +                               ifNotNil: [:escapeSequence |
> > +                                       stream
> > +                                               nextPut: $&;
> > +                                               nextPutAll:
> escapeSequence;
> > +                                               nextPut: $;]]]!
> >
> > Item was added:
> > + ----- Method: SequenceableCollection>>indexOf:from:to:ifAbsent: (in
> category 'accessing') -----
> > + indexOf: anElement from: start to: end ifAbsent: exceptionBlock
> > +       "Answer the index of the first occurence of anElement from start
> to stop
> > +        within the receiver. If the receiver does not contain anElement
> in the,
> > +        range answer the       result of evaluating the argument,
> exceptionBlock."
> > +
> > +       start to: end do:
> > +               [:index |
> > +               (self at: index) = anElement ifTrue: [^index]].
> > +       ^exceptionBlock value!
> >
> >
> >
> >
> >
> > --
> > _,,,^..^,,,_
> > best, Eliot
> >
>
>
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20170209/fa2325de/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: scanForInstructionSequence: Blog Post Workspace.png
Type: image/png
Size: 101131 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20170209/fa2325de/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: scanForInstructionSequence: Blog Post Workspace.png
Type: image/png
Size: 101131 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20170209/fa2325de/attachment-0003.png>


More information about the Squeak-dev mailing list