311 lines
11 KiB
Smalltalk
311 lines
11 KiB
Smalltalk
"
|
|
Pillar ASText delegates the text behavior into a pillar AST .
|
|
"
|
|
Class {
|
|
#name : #GrafoscopioPillarASText,
|
|
#superclass : #GrafoscopioAbstractText,
|
|
#instVars : [
|
|
'ast',
|
|
'stringDecorator',
|
|
'lastNode',
|
|
'runs'
|
|
],
|
|
#category : #'Grafoscopio-Pillar'
|
|
}
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText class >> openExample [
|
|
^ self new
|
|
ast: self pillarExample;
|
|
yourself
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText class >> pillarExample [
|
|
^ PRPillarParser
|
|
parse:
|
|
'!!About Pillar
|
|
|
|
Pillar is a system to manage documents (books, presentations, and web sites). From a common format, it is able to generate documents in multiple formats (html, markdown, latex, AsciiDoc).
|
|
It is composed of several modules such as importers, transformers, document model and outputers.
|
|
|
|
This book describes Pillar in its current version 7.0. Pillar is currently developed and masintained by Stéphane Ducasse and Guillermo Polito.
|
|
The original author of Pillar was Damien Cassou. Many people have also contributed to Pillar: Ben Coman, Guillermo Polito, Lukas Renggli (original author of the PierCMS from which a first version of Pillar has been extracted), Benjamin van Ryseghem, Cyril Ferlicot-Delbecque, Thibault Arloing, Yann Dubois, Quentin Ducasse and Asbathou Sama Biyalou. Special thanks to Asbathou Sama Biyalou!
|
|
|
|
This book adapts, extends, and clarifies the chapter explaining Pillar in the ''Enterprise Pharo: a Web Perspective'' book.
|
|
|
|
Pillar was sponsored by *ESUG>http://www.esug.org*.
|
|
|
|
!!!Introduction
|
|
|
|
Pillar (hosted at *http://github.com/pillar-markup*) is a markup language and associated tools to write and generate documentation, books (such as this one), web sites, and slide-based presentations. The Pillar screenshot in Figure *@voyageDocExample* shows the HTML version of chapter Voyage.
|
|
|
|
+An example Pillar output>file://figures/voyageDocExample-small.png|label=voyageDocExample|width=60+
|
|
|
|
Pillar has many features, helpful tools, and documentation:
|
|
- simple markup syntax with references, tables, pictures, captions, syntax-highlighted code blocks;
|
|
- export documents to HTML, LaTeX, Markdown, AsciiDoc, ePuB and Pillar itself, and presentations to Beamer and Deck.js;
|
|
%- customization of the export through a dedicated STON configuration file (see chapter Missing Chapter *@cha:ston*) and Mustache templates (see chapter *@templating*).
|
|
- many tests with good coverage (94% with more than a 2100 executed tests), which are regularly run by a *continuous integration job>https://ci.inria.fr/pharo-contribution/job/Pillar*
|
|
- a command-line interface and dedicated plugins for several text editors: *Emacs>https://github.com/pillar-markup/pillar-mode*, *Vim>https://github.com/cdlm/vim-pillar*, *TextMate>https://github.com/Uko/Pillar.tmbundle*, and *Atom>https://github.com/Uko/language-pillar*
|
|
- a cheat sheet (see Chapter *@chacheat*).
|
|
|
|
|
|
!!!Pillar users
|
|
|
|
@pillarUSERS
|
|
|
|
This book was written in Pillar itself. If you want to see how Pillar is used, have a look at its source code (*http://github.com/SquareBracketAssociates/Booklet-PublishingAPillarBooklet*), or check the following other real-world projects:
|
|
|
|
- the Updated Pharo by Example book (*https://github.com/SquareBracketAssociates/UpdatedPharoByExample*),
|
|
- the Pharo MOOC - Massive open online course (*https://github.com/SquareBracketAssociates/PharoMooc*,
|
|
- Any of the Pharo booklets (*https://github.com/SquareBracketAssociates/Booklet-XXXX*,
|
|
- the PillarHub open-access shared blog (*http://pillarhub.pharocloud.com*).
|
|
|
|
|
|
!!! Pillar future features
|
|
|
|
Pillar 70 saw some major refactorings and cleaning: it does not rely on Grease and Magritte anymore.
|
|
Its architecture is a lot cleaner.
|
|
|
|
Still some issues are missing. Here is a little list of features that we are working on or will soon:
|
|
|
|
- Incremental recompilation. Since we remove the use of make (so that Windows users can use Pillar) we should introduce a way to avoid to recompile complete book when just one chapter changed.
|
|
- Markdown syntax.
|
|
- Release of Ecstatic. Pillar supports the deployment of web sites named Ecstatic and we are working on a second version of Ecstatic.
|
|
- Better table support.
|
|
|
|
!!! Conclusion
|
|
|
|
|
|
Pillar is still in active development: maintainers keep improving its implementation. The current version of Pillar is Pillar 70. This booklet only documents Pillar 70. This booklet will be synchronised with future enhancements.'
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> ast [
|
|
^ ast
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> ast: aPRDocument [
|
|
ast := aPRDocument.
|
|
aPRDocument accept: GrafoscopioPillarTextAnnotator new.
|
|
ast start: aPRDocument children first start.
|
|
ast stop: aPRDocument children last stop.
|
|
stringDecorator := GrafoscopioPillarASTextStringDecorator new
|
|
text: self;
|
|
yourself
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioPillarASText >> at: anInteger [
|
|
|
|
| node |
|
|
|
|
(anInteger > (self size +1 ) or: [ anInteger < 1 ])
|
|
ifTrue: [ ^ self errorSubscriptBounds: anInteger ].
|
|
node := self detectAstNodeFor: anInteger in: ast.
|
|
|
|
^ node formattedText at: anInteger - node textStart +1
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> attributesAt: characterIndex do: aBlockClosure [
|
|
self size = 0 ifTrue:[^self].
|
|
(self runs at: characterIndex) do: aBlockClosure
|
|
]
|
|
|
|
{ #category : #copying }
|
|
GrafoscopioPillarASText >> copyFrom: from to: to [
|
|
^ (ast textStart = from and: [ ast textStop = (to + 1) ])
|
|
ifTrue: [ self ]
|
|
ifFalse: [ GrafoscopioPillarASTextStringProjectionDecorator new
|
|
text: self;
|
|
|
|
from: from;
|
|
to: to;
|
|
yourself ]
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> detectAstNodeFor: anInteger [
|
|
^ self detectAstNodeFor: anInteger in: ast
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> detectAstNodeFor: anInteger in: aNode [
|
|
(lastNode isNotNil
|
|
and: [ anInteger between: lastNode textStart and: lastNode textStop -1 ])
|
|
ifTrue: [ ^ lastNode ].
|
|
(anInteger between: aNode textStart and: aNode textStop)
|
|
ifFalse: [ self error: 'Cannot find a node for ' , anInteger asString ].
|
|
^ aNode hasChildren
|
|
ifTrue: [ aNode children
|
|
detect: [ :c | anInteger between: c textStart and: c textStop -1 ]
|
|
ifFound: [ :n | self detectAstNodeFor: anInteger in: n ]
|
|
ifNone: [ self error: 'whut?' ] ]
|
|
ifFalse: [ lastNode := aNode ]
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> detectAstNodesBetween: from and: to in: aNode [
|
|
| current nodes |
|
|
nodes := OrderedCollection new.
|
|
current := self detectAstNodeFor: from.
|
|
from > to
|
|
ifTrue: [ nodes add: current ]
|
|
ifFalse: [ [ current isNotNil and: [ current textStart <= to ] ]
|
|
whileTrue: [ nodes add: current.
|
|
current := current next ] ].
|
|
^ nodes
|
|
|
|
|
|
|
|
"| children childrenStream currentNode |
|
|
aNode hasChildren ifFalse: [ ^ {aNode} ].
|
|
childrenStream := aNode children readStream.
|
|
children := OrderedCollection new.
|
|
|
|
[ childrenStream atEnd not and: [ (currentNode :=childrenStream next) textStart <= to ] ] whileTrue:[
|
|
((currentNode textStart >= from) or: [ currentNode textStop >= from ]) ifTrue: [
|
|
children addAll: (self detectAstNodesBetween: from and: to in: currentNode ) .
|
|
].
|
|
].
|
|
^ children."
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> detectFullBranchFor: anId [
|
|
^ self detectFullBranchFor: anId in: ast.
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> detectFullBranchFor: anInteger in: aNode [
|
|
(anInteger between: aNode textStart and: aNode textStop -1 )
|
|
ifFalse: [ self error: 'Cannot find a node for ' , anInteger asString ].
|
|
^ aNode hasChildren
|
|
ifTrue: [ | sub |
|
|
sub := aNode children
|
|
detect: [ :c | anInteger between: c textStart and: c textStop -1 ].
|
|
{aNode} , (self detectFullBranchFor: anInteger in: sub) ]
|
|
ifFalse: [ {aNode} ]
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> extractStringFrom: aPosition to: anOtherPosition [
|
|
| from to nodes preffix suffix |
|
|
nodes := self detectAstNodesBetween: aPosition and: anOtherPosition in: ast.
|
|
from := (aPosition - nodes first textStart +1 ) .
|
|
nodes size = 1 ifTrue: [
|
|
^ nodes first text copyFrom: from to: from + anOtherPosition - aPosition .
|
|
].
|
|
to := nodes last textStop - anOtherPosition.
|
|
|
|
preffix := nodes first formattedText copyFrom: from to: nodes first textSize.
|
|
suffix := nodes last formattedText copyFrom: 1 to: to.
|
|
^ String
|
|
streamContents: [ :str |
|
|
str nextPutAll: preffix.
|
|
(nodes copyFrom: 2 to: nodes size)
|
|
inject: str
|
|
into: [ :stream :each |
|
|
stream nextPutAll: each text.
|
|
stream ].
|
|
str nextPutAll: suffix ]
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> fontAt: characterIndex withStyle: aTextStyle [
|
|
"Answer the fontfor characters in the run beginning at characterIndex."
|
|
| attributes font |
|
|
self size = 0 ifTrue: [^ aTextStyle defaultFont]. "null text tolerates access"
|
|
attributes := runs at: characterIndex.
|
|
font := aTextStyle defaultFont. "default"
|
|
attributes do:
|
|
[:att | att forFontInStyle: aTextStyle do: [:f | font := f]].
|
|
^ font
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> rangeOf: aTextURL startingAt: anInteger [
|
|
^ self runs rangeOf: aTextURL startingAt: anInteger
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> reannotate: aPRText [
|
|
| current previous size parents |
|
|
|
|
aPRText textStop: aPRText textStart + aPRText formattedText size.
|
|
parents := Set new.
|
|
parents add: aPRText parent.
|
|
current := aPRText next.
|
|
|
|
previous := aPRText.
|
|
|
|
[ current isNotNil ]
|
|
whileTrue: [
|
|
size := current textSize.
|
|
current textStart: previous textStop.
|
|
current textStop: current textStart + size.
|
|
previous := current.
|
|
current := current next.
|
|
self ].
|
|
|
|
|
|
self resetRuns.
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioPillarASText >> removeAttribute: att from: start to: stop [
|
|
|
|
]
|
|
|
|
{ #category : #editing }
|
|
GrafoscopioPillarASText >> replaceFrom: start to: stop with: aCollection [
|
|
| nodes realStart realStop newText node |
|
|
aCollection ifEmpty: [ ^ self ].
|
|
nodes := self detectAstNodesBetween: start and: stop in: ast.
|
|
self assert: nodes size = 1.
|
|
node := nodes first.
|
|
realStart := (start - (node textStart + node leftFormatSize) )+ 1 .
|
|
realStop := stop - (node textStart + node rightFormatSize) + 1 .
|
|
newText := (node text copyReplaceFrom: realStart to: realStop with: aCollection).
|
|
node isText ifTrue: [
|
|
node text: newText
|
|
] ifFalse: [
|
|
(newText beginsWith: node text) ifTrue: [
|
|
nodes := self detectAstNodesBetween: start - 1 and: start -1 in: ast.
|
|
nodes first text: nodes first text , (newText copyFrom: node text size to: newText size ).
|
|
] ifFalse: [
|
|
nodes first next text: (newText copyFrom: 1 to: newText size - node textSize) , nodes first text.
|
|
]
|
|
].
|
|
self reannotate: nodes first.
|
|
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioPillarASText >> resetRuns [
|
|
^ runs := GrafoscopioPillarRuns new
|
|
ast: self;
|
|
yourself
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioPillarASText >> runs [
|
|
^ runs
|
|
ifNil: [ runs := GrafoscopioPillarRuns new
|
|
ast: self;
|
|
yourself ]
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioPillarASText >> size [
|
|
^ ast textSize
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioPillarASText >> string [
|
|
^ stringDecorator
|
|
]
|