SystemOrganization addCategory: #'TextLint-Model'!
SystemOrganization addCategory: #'TextLint-Model-Parser'!
SystemOrganization addCategory: #'TextLint-Model-Rules'!
SystemOrganization addCategory: #'TextLint-Model-Runner'!
PPCompositeParser subclass: #TLCachedParser
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
TLCachedParser class
instanceVariableNames: 'instance'!
TLCachedParser class
instanceVariableNames: 'instance'!
!TLCachedParser class methodsFor: 'private' stamp: 'lr 5/4/2011 23:32'!
compile: aTextString classified: aCategorySymbol withStamp: aStampString notifying: aRequestor logSource: aBoolean
self flush.
^ super compile: aTextString classified: aCategorySymbol withStamp: aStampString notifying: aRequestor logSource: aBoolean! !
!TLCachedParser class methodsFor: 'private' stamp: 'lr 5/4/2011 23:29'!
flush
self subclasses do: [ :each | each flush ].
instance := nil! !
!TLCachedParser class methodsFor: 'instance creation' stamp: 'lr 5/4/2011 23:29'!
newStartingAt: aSymbol
^ instance ifNil: [ instance := super newStartingAt: aSymbol ]! !
TLCachedParser subclass: #TLDocumentPhraser
instanceVariableNames: 'document documentTerminator paragraph paragraphTerminator sentence sentenceTerminator'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
!TLDocumentPhraser methodsFor: 'grammar' stamp: 'lr 11/3/2010 16:28'!
document
^ (paragraph starLazy: documentTerminator) , (documentTerminator optional)! !
!TLDocumentPhraser methodsFor: 'grammar' stamp: 'JorgeRessia 6/12/2010 12:19'!
documentTerminator
^ PPPredicateObjectParser
on: [ :token | token isEndOfDocument ]
message: 'End of document expected'! !
!TLDocumentPhraser methodsFor: 'grammar' stamp: 'lr 11/3/2010 16:28'!
paragraph
^ (sentence starLazy: paragraphTerminator / documentTerminator) , (paragraphTerminator optional) ! !
!TLDocumentPhraser methodsFor: 'grammar' stamp: 'JorgeRessia 6/12/2010 12:20'!
paragraphTerminator
^ PPPredicateObjectParser
on: [ :token | token isWhitespace and: [ token isEndOfParagraph ] ]
message: 'End of paragraph expected'! !
!TLDocumentPhraser methodsFor: 'grammar' stamp: 'lr 11/3/2010 16:29'!
sentence
^ (#any asParser starLazy: sentenceTerminator / paragraphTerminator / documentTerminator) , (sentenceTerminator optional)! !
!TLDocumentPhraser methodsFor: 'grammar' stamp: 'JorgeRessia 6/12/2010 12:20'!
sentenceTerminator
^ PPPredicateObjectParser
on: [ :token | token isPunctuation and: [ token isEndOfSentence ] ]
message: 'End of sentence expected'! !
!TLDocumentPhraser methodsFor: 'accessing' stamp: 'lr 4/6/2010 21:43'!
start
^ document end! !
TLDocumentPhraser subclass: #TLTextPhraser
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
!TLTextPhraser methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:28'!
document
^ super document ==> [ :nodes | TLDocument withAll: nodes first ]! !
!TLTextPhraser methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:28'!
paragraph
^ super paragraph ==> [ :nodes |
TLParagraph withAll: (nodes last isNil
ifFalse: [ nodes first copyWith: nodes last ]
ifTrue: [ nodes first ]) ]! !
!TLTextPhraser methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:29'!
sentence
^ super sentence ==> [ :nodes |
TLSentence withAll: (nodes last isNil
ifFalse: [ nodes first copyWith: nodes last ]
ifTrue: [ nodes first ]) ]! !
TLCachedParser subclass: #TLTextTokenizer
instanceVariableNames: 'elementList element markup word whitespace punctuation punctuationGroups unknown punctuationCharacters'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
TLTextTokenizer subclass: #TLPatternTokenizer
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
!TLPatternTokenizer methodsFor: 'grammar' stamp: 'lr 9/5/2011 18:36'!
elementList
"We need at least one term, otherwise we would match anything."
^ element plus foldLeft: [ :a :b | a , b ]! !
!TLPatternTokenizer methodsFor: 'token' stamp: 'lr 9/5/2011 18:45'!
markup
^ ${ asParser , #word asParser plus token , $} asParser map: [ :open :token :close |
| type |
type := token value asSymbol.
(TLWordClassifier types includes: type)
ifFalse: [ PPFailure message: 'Invalid word type: ' , token value at: token start ]
ifTrue: [
PPPredicateObjectParser
on: [ :each | each isWord and: [ each classification includes: type ] ]
message: token value , ' expected' ] ]! !
!TLPatternTokenizer methodsFor: 'token' stamp: 'lr 9/5/2011 18:26'!
punctuation
^ super punctuation ==> [ :token |
PPPredicateObjectParser
on: [ :each | each isPunctuation and: [ each text = token value ] ]
message: token value printString , ' expected' ]! !
!TLPatternTokenizer methodsFor: 'token' stamp: 'lr 9/5/2011 18:53'!
punctuationCharacters
"Remove the open and close curly-braces."
^ PPPredicateObjectParser chars: '''"[]():,-!!.?;/&@' message: 'Punctuation expected'! !
!TLPatternTokenizer methodsFor: 'accessing' stamp: 'lr 9/5/2011 18:36'!
start
^ super start ==> [ :node | node flatten ]! !
!TLPatternTokenizer methodsFor: 'token' stamp: 'lr 9/5/2011 18:28'!
unknown
^ PPFailingParser message: 'Invalid query character'! !
!TLPatternTokenizer methodsFor: 'token' stamp: 'lr 11/30/2010 19:38'!
whitespace
^ super whitespace ==> [ :token |
(PPPredicateObjectParser
on: [ :each | each isWhitespace or: [ each isMarkup ] ]
message: 'whitespace expected') star ]! !
!TLPatternTokenizer methodsFor: 'token' stamp: 'lr 11/3/2010 16:36'!
word
^ super word ==> [ :token |
PPPredicateObjectParser
on: [ :each | each isWord and: [ each text sameAs: token value ] ]
message: token value printString , ' expected' ]! !
TLTextTokenizer subclass: #TLPlainTokenizer
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
TLPlainTokenizer subclass: #TLHtmlTokenizer
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
!TLHtmlTokenizer class methodsFor: 'testing' stamp: 'lr 9/9/2011 20:41'!
canTokenize: aString
^ #(' asParser negate plus , $> asParser)
/ ($& asParser , $; asParser negate plus , $; asParser))
token ==> [ :token | TLMarkup with: token ]! !
TLPlainTokenizer subclass: #TLLatexTokenizer
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Parser'!
!TLLatexTokenizer class methodsFor: 'testing' stamp: 'lr 9/9/2011 20:41'!
canTokenize: aString
^ #('\documentclass' '\usepackage' '\section' '\begin{') anySatisfy: [ :each | aString includesSubstring: each caseSensitive: false ]! !
!TLLatexTokenizer methodsFor: 'private' stamp: 'lr 5/31/2010 07:36'!
consumeCommand: aStream
| counter char |
('{[' includes: aStream peek)
ifFalse: [ ^ self ].
counter := 0.
[ char := aStream next.
(char = ${ or: [ char = $[ ])
ifTrue: [ counter := counter + 1 ]
ifFalse: [
(char = $} or: [ char = $] ])
ifTrue: [ counter := counter - 1 ] ].
aStream atEnd or: [ counter = 0 ] ] whileFalse.
self consumeCommand: aStream! !
!TLLatexTokenizer methodsFor: 'private' stamp: 'lr 5/31/2010 07:35'!
consumeEnvironment: aStream
aStream upToAll: '\end{' , (aStream upTo: $}) , '}'! !
!TLLatexTokenizer methodsFor: 'configuration' stamp: 'lr 9/25/2011 16:06'!
ignoredCommands
^ #('begin' 'bibliography' 'bibliographystyle' 'cite' 'documentclass' 'end' 'hspace' 'hypersetup' 'index' 'label' 'lstset' 'newcommand' 'newenviornment' 'renewcommand' 'usepackage' 'vspace') asSet asParser! !
!TLLatexTokenizer methodsFor: 'configuration' stamp: 'lr 5/31/2010 07:34'!
ignoredEnvironments
^ #('lstlisting' 'figure' 'table') asSet asParser! !
!TLLatexTokenizer methodsFor: 'tokens' stamp: 'lr 9/9/2011 20:20'!
markup
^ ((PPPredicateObjectParser anyOf: '{}[]`-')
/ ('\begin{' asParser , self ignoredEnvironments and , [ :stream | self consumeEnvironment: stream ] asParser)
/ ($\ asParser , self ignoredCommands , [ :stream | self consumeCommand: stream ] asParser)
/ ($\ asParser , #any asParser , #word asParser star)
/ ($$ asParser , $$ asParser negate star , $$ asParser)
/ ($% asParser , #newline asParser negate star))
token ==> [ :token | TLMarkup with: token ]! !
!TLLatexTokenizer methodsFor: 'tokens' stamp: 'lr 9/5/2011 18:35'!
punctuationGroups
^ super punctuationGroups / '``' asParser / '''''' asParser / '---' asParser / '--' asParser! !
!TLPlainTokenizer class methodsFor: 'testing' stamp: 'lr 9/9/2011 20:45'!
canTokenize: aString
"Answer true if the receiving class can easily tokenize aString."
^ self name = #TLPlainTokenizer! !
!TLPlainTokenizer class methodsFor: 'finding' stamp: 'lr 9/9/2011 20:43'!
find: aString
"Finds an appropritate tokenizer for aString."
^ (self allSubclasses
detect: [ :class | class canTokenize: aString ]
ifNone: [ self ])
new! !
!TLPlainTokenizer methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:31'!
elementList
^ super elementList ==> [ :nodes | nodes copyWith: (TLTerminatorMark with: '') ]! !
!TLPlainTokenizer methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:32'!
punctuation
^ super punctuation ==> [ :node | TLPunctuationMark with: node ]! !
!TLPlainTokenizer methodsFor: 'accessing' stamp: 'lr 9/5/2011 18:34'!
unknown
^ super unknown ==> [ :token | TLMarkup with: token ]! !
!TLPlainTokenizer methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:33'!
whitespace
^ super whitespace ==> [ :node | TLWhitespace with: node ]! !
!TLPlainTokenizer methodsFor: 'accessing' stamp: 'lr 11/3/2010 16:32'!
word
^ super word ==> [ :node | TLWord with: node ]! !
!TLTextTokenizer methodsFor: 'grammar' stamp: 'lr 9/5/2011 18:20'!
element
^ markup / word / whitespace / punctuation / unknown! !
!TLTextTokenizer methodsFor: 'grammar' stamp: 'lr 11/3/2010 16:31'!
elementList
^ element star! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 5/27/2010 16:27'!
markup
^ PPFailingParser message: 'Markup expected'! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 9/5/2011 18:21'!
punctuation
^ (punctuationGroups / punctuationCharacters) token! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 9/5/2011 18:24'!
punctuationCharacters
^ PPPredicateObjectParser chars: '''"[](){}:,-!!.?;/&@' message: 'Punctuation expected'! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 5/28/2010 11:59'!
punctuationGroups
^ '...' asParser! !
!TLTextTokenizer methodsFor: 'accessing' stamp: 'lr 9/5/2011 18:31'!
start
^ elementList end! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 9/5/2011 18:34'!
unknown
^ #any asParser token! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 11/3/2010 16:32'!
whitespace
^ #space asParser plus token! !
!TLTextTokenizer methodsFor: 'tokens' stamp: 'lr 11/3/2010 16:32'!
word
^ #word asParser plus token! !
Object subclass: #TLElement
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
TLElement subclass: #TLDocument
instanceVariableNames: 'paragraphs'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLDocument class methodsFor: 'instance creation' stamp: 'lr 3/31/2010 11:15'!
withAll: aCollection
^self new initializeWithAll: aCollection! !
!TLDocument methodsFor: 'accessing' stamp: 'JorgeRessia 5/26/2010 09:27'!
allElements
^OrderedCollection new
add: self;
addAll: paragraphs;
addAll: self sentences;
addAll: self words;
yourself.! !
!TLDocument methodsFor: 'checking' stamp: 'JorgeRessia 5/26/2010 10:12'!
checkWith: aTextLintChecker
^aTextLintChecker checkDocument: self! !
!TLDocument methodsFor: 'accessing' stamp: 'lr 4/6/2010 21:15'!
children
^ paragraphs! !
!TLDocument methodsFor: 'initialization' stamp: 'lr 3/31/2010 11:16'!
initializeWithAll: aCollection
paragraphs := aCollection! !
!TLDocument methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 12:11'!
isDocument
^ true! !
!TLDocument methodsFor: 'accessing' stamp: 'lr 3/31/2010 11:22'!
paragraphs
^paragraphs ! !
!TLDocument methodsFor: 'visiting' stamp: 'JorgeRessia 6/16/2010 15:30'!
processFor: aVisitor
^ aVisitor processDocument: self! !
!TLDocument methodsFor: 'accessing' stamp: 'lr 3/31/2010 11:24'!
sentences
^ self paragraphs gather: [ :each | each sentences ]! !
!TLDocument methodsFor: 'accessing' stamp: 'lr 3/31/2010 11:24'!
words
^self sentences gather: [ :each | each words ]! !
!TLElement methodsFor: 'checking' stamp: 'lr 5/27/2010 16:25'!
checkWith: aTextLintChecker
self subclassResponsibility! !
!TLElement methodsFor: 'accessing' stamp: 'lr 4/6/2010 20:30'!
children
"Answer the children nodes."
^ #()
! !
!TLElement methodsFor: 'accessing' stamp: 'lr 4/9/2010 10:54'!
interval
"Answer the interval in the text in which the receiver is defined."
^ self start to: self stop! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 12:11'!
isDocument
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 11:44'!
isEndOfDocument
^ false! !
!TLElement methodsFor: 'testing' stamp: 'lr 5/27/2010 16:24'!
isMarkup
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 12:11'!
isParagraph
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/9/2010 14:06'!
isPhrase
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 11:44'!
isPunctuation
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 12:10'!
isSentence
^ false! !
!TLElement methodsFor: 'testing' stamp: 'DamienCassou 11/21/2011 20:00'!
isSyntacticElement
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 11:44'!
isWhitespace
^ false! !
!TLElement methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 11:44'!
isWord
^ false! !
!TLElement methodsFor: 'printing' stamp: 'JorgeRessia 4/8/2010 10:49'!
printContentOn: aStream
self children do: [ :each | aStream nextPutAll: each text ]! !
!TLElement methodsFor: 'printing' stamp: 'lr 4/8/2010 13:29'!
printOn: aStream
super printOn: aStream.
aStream nextPutAll: ' ('.
self printContentOn: aStream.
aStream nextPut: $)! !
!TLElement methodsFor: 'accessing' stamp: 'lr 4/9/2010 10:56'!
start
"Answer the start position of the receiver."
^ self children isEmpty
ifFalse: [ self children first start ]
ifTrue: [ 1 ]! !
!TLElement methodsFor: 'accessing' stamp: 'lr 4/9/2010 11:02'!
stop
"Answer the end position of the receiver."
^ self children isEmpty
ifFalse: [ self children last stop ]
ifTrue: [ 0 ]! !
!TLElement methodsFor: 'accessing' stamp: 'lr 4/6/2010 22:09'!
text
^ String streamContents: [ :stream | self printContentOn: stream ]! !
!TLElement methodsFor: 'accessing' stamp: 'lr 6/16/2010 08:18'!
token
"Answer the first token in the receiver or nil."
^ self children isEmpty ifFalse: [ self children first token ]! !
TLElement subclass: #TLParagraph
instanceVariableNames: 'sentences'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLParagraph class methodsFor: 'instance creation' stamp: 'JorgeRessia 4/7/2010 11:13'!
withAll: aCollection
^self new initializeWithAll: aCollection! !
!TLParagraph methodsFor: 'checking' stamp: 'JorgeRessia 5/26/2010 10:20'!
checkWith: aTextLintChecker
^aTextLintChecker checkParagraph: self! !
!TLParagraph methodsFor: 'accessing' stamp: 'lr 4/6/2010 21:15'!
children
^ sentences! !
!TLParagraph methodsFor: 'initialization' stamp: 'lr 3/31/2010 11:17'!
initializeWithAll: aCollection
sentences := aCollection! !
!TLParagraph methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 12:11'!
isParagraph
^ true! !
!TLParagraph methodsFor: 'visiting' stamp: 'JorgeRessia 6/16/2010 15:30'!
processFor: aVisitor
^ aVisitor processParagraph: self! !
!TLParagraph methodsFor: 'accessing' stamp: 'JorgeRessia 4/7/2010 11:13'!
sentences
^sentences reject: [:eachElement | eachElement isWhitespace]! !
!TLParagraph methodsFor: 'accessing' stamp: 'JorgeRessia 4/12/2010 10:48'!
words
^self sentences gather: [ :each | each words ]! !
TLElement subclass: #TLPhrase
instanceVariableNames: 'syntacticElements'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLPhrase class methodsFor: 'instance creation' stamp: 'JorgeRessia 4/8/2010 14:52'!
withAll: aCollection
^self new initializeWithAll: aCollection! !
!TLPhrase methodsFor: 'accessing' stamp: 'JorgeRessia 4/8/2010 14:57'!
children
^ syntacticElements! !
!TLPhrase methodsFor: 'initialization' stamp: 'JorgeRessia 4/8/2010 14:56'!
initializeWithAll: aCollection
syntacticElements := aCollection! !
!TLPhrase methodsFor: 'testing' stamp: 'JorgeRessia 4/9/2010 14:06'!
isPhrase
^ true! !
!TLPhrase methodsFor: 'accessing' stamp: 'JorgeRessia 9/3/2010 10:04'!
phraseWithoutMarkups
^ TLPhrase withAll: (syntacticElements select: [:eachToken | eachToken isMarkup not ])! !
!TLPhrase methodsFor: 'visiting' stamp: 'JorgeRessia 6/16/2010 15:31'!
processFor: aVisitor
^ aVisitor processPhrase: self! !
!TLPhrase methodsFor: 'accessing' stamp: 'JorgeRessia 9/23/2010 22:02'!
size
^self words size! !
!TLPhrase methodsFor: 'accessing' stamp: 'JorgeRessia 4/8/2010 14:56'!
words
^ syntacticElements select: [:eachToken | eachToken isWord ]! !
TLElement subclass: #TLSentence
instanceVariableNames: 'syntacticElements phrasesCache sequencesCache'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLSentence class methodsFor: 'instance creation' stamp: 'lr 3/31/2010 11:17'!
withAll: aCollection
^self new initializeWithAll: aCollection! !
!TLSentence methodsFor: 'accessing' stamp: 'JorgeRessia 5/26/2010 13:49'!
allPhrasesOfSize: aSmallInteger
| phrases words |
phrasesCache at: aSmallInteger ifPresent: [:element | ^element].
phrases := OrderedCollection new.
words := self words.
1 to: words size
do: [ :index | ((index + aSmallInteger - 1) <= words size)
ifTrue: [ phrases add: (TLPhrase withAll: ( syntacticElements
copyFrom: (syntacticElements indexOf: (words at: index ))
to: (syntacticElements indexOf: (words at: index + aSmallInteger - 1))))]
ifFalse: [ phrasesCache at: aSmallInteger put: phrases.
^phrases] ].
phrasesCache at: aSmallInteger put: phrases.
^phrases
! !
!TLSentence methodsFor: 'accessing' stamp: 'JorgeRessia 6/10/2010 15:45'!
allSequencesOfSize: aSmallInteger
| sequences children|
sequencesCache at: aSmallInteger ifPresent: [:element | ^element].
sequences := OrderedCollection new.
children := self children.
1 to: children size
do: [ :index | ((index + aSmallInteger - 1) <= children size)
ifTrue: [ sequences add: (TLPhrase withAll: ( syntacticElements
copyFrom: (syntacticElements indexOf: (children at: index ))
to: (syntacticElements indexOf: (children at: index + aSmallInteger - 1))))]
ifFalse: [ sequencesCache at: aSmallInteger put: sequences.
^sequences] ].
sequencesCache at: aSmallInteger put: sequences.
^sequences
! !
!TLSentence methodsFor: 'checking' stamp: 'JorgeRessia 5/26/2010 10:41'!
checkWith: aTextLintChecker
^aTextLintChecker checkSentence: self! !
!TLSentence methodsFor: 'accessing' stamp: 'JorgeRessia 4/8/2010 11:08'!
children
^ syntacticElements! !
!TLSentence methodsFor: 'testing' stamp: 'lr 4/5/2010 10:25'!
containsPhrase: aString
^ self wordsAsString includesSubstring: aString caseSensitive: false! !
!TLSentence methodsFor: 'initialization' stamp: 'JorgeRessia 6/10/2010 15:30'!
initializeWithAll: aCollection
syntacticElements := aCollection.
phrasesCache := Dictionary new.
sequencesCache := Dictionary new.! !
!TLSentence methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 12:12'!
isSentence
^ true! !
!TLSentence methodsFor: 'visiting' stamp: 'JorgeRessia 6/16/2010 15:31'!
processFor: aVisitor
^ aVisitor processSentence: self! !
!TLSentence methodsFor: 'accessing' stamp: 'JorgeRessia 4/8/2010 11:08'!
words
^ syntacticElements select: [:eachToken | eachToken isWord ]! !
!TLSentence methodsFor: 'accessing' stamp: 'JorgeRessia 4/7/2010 15:24'!
wordsAsString
^self words inject: '' into: [:count :each | count, ' ', each text] ! !
TLElement subclass: #TLSyntacticElement
instanceVariableNames: 'token'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
TLSyntacticElement subclass: #TLMarkup
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLMarkup methodsFor: 'testing' stamp: 'lr 5/27/2010 16:24'!
isMarkup
^ true! !
TLSyntacticElement subclass: #TLPunctuationMark
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLPunctuationMark methodsFor: 'testing' stamp: 'JorgeRessia 4/7/2010 13:58'!
isEndOfSentence
^ '.:;!!?' includes: (token collection at: token start)! !
!TLPunctuationMark methodsFor: 'testing' stamp: 'lr 4/6/2010 20:44'!
isPunctuation
^ true! !
!TLSyntacticElement class methodsFor: 'instance creation' stamp: 'lr 4/8/2010 13:31'!
with: aToken
^ self new initializeWith: aToken! !
!TLSyntacticElement methodsFor: 'initialization' stamp: 'lr 4/8/2010 13:31'!
initializeWith: aToken
token := aToken! !
!TLSyntacticElement methodsFor: 'testing' stamp: 'DamienCassou 11/21/2011 20:00'!
isSyntacticElement
^ true! !
!TLSyntacticElement methodsFor: 'printing' stamp: 'lr 4/8/2010 13:52'!
printContentOn: aStream
aStream nextPutAll: self text! !
!TLSyntacticElement methodsFor: 'visiting' stamp: 'JorgeRessia 6/16/2010 15:32'!
processFor: aVisitor
^ aVisitor processSyntacticElement: self! !
!TLSyntacticElement methodsFor: 'accessing' stamp: 'lr 4/9/2010 10:57'!
start
^ self token start! !
!TLSyntacticElement methodsFor: 'accessing' stamp: 'lr 4/9/2010 10:57'!
stop
^ self token stop! !
!TLSyntacticElement methodsFor: 'accessing' stamp: 'JorgeRessia 4/7/2010 13:54'!
text
^ token value! !
!TLSyntacticElement methodsFor: 'accessing' stamp: 'JorgeRessia 4/8/2010 10:56'!
token
^ token! !
TLSyntacticElement subclass: #TLTerminatorMark
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLTerminatorMark methodsFor: 'testing' stamp: 'lr 4/6/2010 22:04'!
isEndOfDocument
^ true! !
TLSyntacticElement subclass: #TLWhitespace
instanceVariableNames: ''
classVariableNames: 'NewLineParser'
poolDictionaries: ''
category: 'TextLint-Model'!
!TLWhitespace class methodsFor: 'initialization' stamp: 'lr 9/7/2011 20:45'!
initialize
"Platform independent newline sequence. LF: Unix, CR+LF: Windows, and CR: Apple."
NewLineParser := (Character lf asParser) / (Character cr asParser , Character lf asParser optional)! !
!TLWhitespace class methodsFor: 'instance creation' stamp: 'lr 9/7/2011 20:45'!
new
^ self basicNew initializeWith: (PPToken on: ' ')! !
!TLWhitespace methodsFor: 'testing' stamp: 'lr 9/7/2011 20:50'!
isEndOfParagraph
| count |
count := 0.
NewLineParser
matchesIn: token value
do: [ :each |
(count := count + 1) = 2
ifTrue: [ ^ true ] ].
^ false! !
!TLWhitespace methodsFor: 'testing' stamp: 'lr 4/6/2010 21:45'!
isWhitespace
^ true! !
TLSyntacticElement subclass: #TLWord
instanceVariableNames: 'type'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLWord methodsFor: 'checking' stamp: 'lr 5/26/2010 14:17'!
checkWith: aTextLintChecker
^ aTextLintChecker checkWord: self! !
!TLWord methodsFor: 'accessing' stamp: 'lr 5/4/2011 20:47'!
classification
^ TLWordClassifier classify: self text! !
!TLWord methodsFor: 'testing' stamp: 'lr 9/6/2011 22:20'!
classifiesAs: aSymbol
"Answer if the receiving word classifies with a certainty of 1.0."
| classifications |
classifications := self classification.
^ classifications size = 1 and: [ classifications first = aSymbol ]! !
!TLWord methodsFor: 'testing' stamp: 'lr 9/6/2011 22:19'!
classifiesAs: aSymbol withCertainty: aFloat
"Answer if the receiving word classifies as aSymbol with a certainty of aFloat (0.0 - 1.0)."
| classifications |
classifications := self classification.
(classifications includes: aSymbol)
ifFalse: [ ^ false ].
(classifications size = 1)
ifTrue: [ ^ true ].
^ 1.0 / classifications size >= aFloat! !
!TLWord methodsFor: 'testing' stamp: 'lr 4/6/2010 20:44'!
isWord
^ true! !
Object subclass: #TLMassPaperAnalysis
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Runner'!
!TLMassPaperAnalysis class methodsFor: 'tools' stamp: 'lr 6/11/2010 15:28'!
analyzeAllHistory: aDirectory
"self analyzeAllHistory: (FileDirectory on: '/Users/renggli/University/git/papers/TextLint/TextLint-IWST2010/casestudy')"
aDirectory directoryNames asSortedCollection
do: [ :each | self analyzeHistory: (aDirectory directoryNamed: each) ]
displayingProgress: 'Analyzing Directories'! !
!TLMassPaperAnalysis class methodsFor: 'tools' stamp: 'lr 9/8/2010 18:46'!
analyzeEffectiveness: aDirectory
"self analyzeEffectiveness: (FileDirectory on: '/Users/renggli/University/git/papers/TextLint/TextLint-IWST2010/casestudy')"
| checker results |
checker := TLTextLintChecker new.
results := OrderedCollection new.
(TLWritingStyle scientificPaperStyle rules
asSortedCollection: [ :a :b | a name < b name ])
do: [ :each | checker addRule: each ].
(aDirectory fileNames asSortedCollection
select: [ :each | each endsWith: '.txt' ])
do: [ :filename |
| stream count last size average |
stream := MultiByteFileStream new initialize.
stream open: (aDirectory fullNameFor: filename) forWrite: false.
stream nextLine.
count := 0.
average := Array new: checker rules size + 1 withAll: 0.
[ stream atEnd ] whileFalse: [
count := count + 1.
last := stream nextLine splitOn: String tab.
size := (last at: 3) asNumber asFloat.
last := (last allButFirst: 3)
collect: [ :each | each asNumber / size ].
average keysAndValuesDo: [ :key :value | average at: key put: value + (last at: key) ] ].
average keysAndValuesDo: [ :key :value | average at: key put: value / count asFloat ].
results addLast: (Array with: filename) , (Array streamContents: [ :output |
average with: last do: [ :a :l |
output nextPut: (a isZero
ifTrue: [ 0 ]
ifFalse: [ (100.0 - (100.0 * l / a)) rounded ]) ] ]) ]
displayingProgress: 'Calculating Effectiveness'.
FileStream forceNewFileNamed: (aDirectory containingDirectory fullNameFor: 'casestudy-effectiveness/effectiveness.txt') do: [ :stream |
stream nextPutAll: 'Filename'; tab; nextPutAll: 'Total'; tab.
checker rules
do: [ :rule | stream nextPutAll: rule name ]
separatedBy: [ stream tab ].
stream cr.
results
do: [ :row |
row
do: [ :col | stream nextPutAll: col asString ]
separatedBy: [ stream tab ] ]
separatedBy: [ stream cr ] ].
^ results! !
!TLMassPaperAnalysis class methodsFor: 'tools' stamp: 'lr 11/3/2010 16:28'!
analyzeHistory: aDirectory
"self analyzeHistory: (FileDirectory on: '/Users/renggli/University/git/papers/TextLint/TextLint-IWST2010/casestudy-history/petitparser')"
"self analyzeHistory: (FileDirectory on: '/Users/renggli/University/git/papers/TextLint/TextLint-IWST2010/casestudy-history/J2EE')"
"self analyzeHistory: (FileDirectory on: '/Users/renggli/University/git/papers/TextLint/TextLint-IWST2010/casestudy-history/cop')"
"self analyzeHistory: (FileDirectory on: '/Users/renggli/University/git/papers/TextLint/TextLint-IWST2010/casestudy-history/pinocchio')"
| checker results |
checker := TLTextLintChecker new.
results := OrderedCollection new.
(TLWritingStyle scientificPaperStyle rules
asSortedCollection: [ :a :b | a name < b name ])
do: [ :each | checker addRule: each ].
aDirectory fileNames asSortedCollection
do: [ :filename |
| stream contents document failures |
stream := MultiByteFileStream new initialize.
stream open: (aDirectory fullNameFor: filename) forWrite: false.
contents := [ stream basicNext: stream size ] ensure: [ stream close ].
document := TLTextPhraser parse: (TLLatexTokenizer parse: contents).
failures := document allElements gather: [ :each | each checkWith: checker ].
results addLast: (Array
with: (filename)
with: (contents size)
with: (document sentences detectSum: [ :sentence |
sentence children detectSum: [ :element |
element class = TLMarkup
ifTrue: [ 0 ]
ifFalse: [ element token size ] ] ])
with: (failures size)) , (checker rules
collect: [ :each | failures count: [ :failure | failure rule == each ] ]) ]
displayingProgress: 'Analyzing History'.
FileStream forceNewFileNamed: (aDirectory containingDirectory fullNameFor: aDirectory localName , '.txt') do: [ :stream |
stream nextPutAll: 'Filename'; tab; nextPutAll: 'Filesize'; tab; nextPutAll: 'Textsize'; tab; nextPutAll: 'Failures'; tab.
checker rules
do: [ :rule | stream nextPutAll: rule name ]
separatedBy: [ stream tab ].
stream cr.
results
do: [ :row |
row
do: [ :col | stream nextPutAll: col asString ]
separatedBy: [ stream tab ] ]
separatedBy: [ stream cr ] ].
^ results! !
!TLMassPaperAnalysis methodsFor: 'private' stamp: 'lr 5/11/2011 21:07'!
analyze
| paperNames allFailures aChecker file fileContents results author checker |
aChecker := TLTextLintChecker new.
TLWritingStyle scientificPaperStyle rules
do: [:rule | aChecker addRule: rule].
allFailures := Dictionary new.
paperNames := (FileDirectory on: '/Users/ressia/temp/Papers/Helvetia') fullNamesOfAllFilesInSubtree
select: [:each | each endsWith: '.tex'].
paperNames
do: [:each |
fileContents := (StandardFileStream readOnlyFileNamed: each) contentsOfEntireFile.
fileContents := (fileContents copyReplaceAll: String crlf with: String cr)
copyReplaceAll: String lf
with: String cr.
author := nil.
(fileContents findString: '% $Author:' startingAt: 1 ) = 0
ifFalse: [author := fileContents copyFrom: (fileContents findString: '% $Author:' startingAt: 1 ) to: (fileContents findDelimiters: '$' startingAt: (fileContents findString: '% $Author:' startingAt: 1 ) )].
(fileContents findString: '\author{' startingAt: 1 ) = 0
ifFalse: [author := fileContents copyFrom: (fileContents findString: '\author{' startingAt: 1 ) to: (fileContents findDelimiters: '}' startingAt: (fileContents findString: '\author{' startingAt: 1 ) )].
checker := aChecker parse: fileContents.
allFailures at: each put: checker results ].
file := CrLfFileStream forceNewFileNamed: '/Users/ressia/temp/SCGPapersTextLintFailures.txt'.
^ allFailures
keysAndValuesDo: [:key :value | value
do: [:eachFailure | file nextPutAll: key;
nextPutAll: ' ';
nextPutAll: author asString;
nextPutAll: ' ';
nextPutAll: eachFailure rule class name;
nextPutAll: ' ';
nextPutAll: eachFailure element text;
nextPutAll: '
']]
! !
Object subclass: #TLRuleFailure
instanceVariableNames: 'rule element'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Runner'!
!TLRuleFailure class methodsFor: 'instance creation' stamp: 'JorgeRessia 4/6/2010 15:54'!
on: aRule at: anElement
^self new initializeOn: aRule at: anElement! !
!TLRuleFailure methodsFor: 'accessing' stamp: 'JorgeRessia 4/6/2010 16:00'!
element
^ element! !
!TLRuleFailure methodsFor: 'initialization' stamp: 'JorgeRessia 4/6/2010 15:55'!
initializeOn: aRule at: anElement
rule := aRule.
element := anElement! !
!TLRuleFailure methodsFor: 'testing' stamp: 'JorgeRessia 5/26/2010 11:40'!
isRuleFailure
^true! !
!TLRuleFailure methodsFor: 'printing' stamp: 'lr 4/8/2010 15:36'!
printOn: aStream
super printOn: aStream.
aStream cr; tab; print: self rule.
aStream cr; tab; print: self element! !
!TLRuleFailure methodsFor: 'accessing' stamp: 'JorgeRessia 4/6/2010 16:00'!
rule
^ rule! !
Object subclass: #TLTextLintChecker
instanceVariableNames: 'rules document results'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Runner'!
!TLTextLintChecker methodsFor: 'accessing' stamp: 'JorgeRessia 3/31/2010 16:49'!
addRule: aRule
rules add: aRule! !
!TLTextLintChecker methodsFor: 'accessing' stamp: 'lr 10/25/2010 19:40'!
addStyle: aStyle
aStyle rules do: [ :each | self addRule: each ]! !
!TLTextLintChecker methodsFor: 'mocking' stamp: 'JorgeRessia 5/26/2010 11:35'!
checkDocument: aDocument
|results |
results := OrderedCollection new.
rules do: [:each | results addAll: (each runOnDocument: aDocument)].
^results
! !
!TLTextLintChecker methodsFor: 'mocking' stamp: 'JorgeRessia 5/26/2010 10:23'!
checkParagraph: aParagraph
| results |
results := OrderedCollection new.
rules do: [:each | results addAll: (each runOnParagraph: aParagraph)].
^results
! !
!TLTextLintChecker methodsFor: 'mocking' stamp: 'lr 5/26/2010 15:09'!
checkSentence: aSentence
^ rules gather: [ :each | each runOnSentence: aSentence ]! !
!TLTextLintChecker methodsFor: 'mocking' stamp: 'JorgeRessia 5/26/2010 10:23'!
checkWord: aWord
| results |
results := OrderedCollection new.
rules do: [:each | results addAll: (each runOnWord: aWord)].
^results
! !
!TLTextLintChecker methodsFor: 'accessing' stamp: 'FabrizioPerin 5/31/2010 14:40'!
document
^ document! !
!TLTextLintChecker methodsFor: 'initializing' stamp: 'lr 5/11/2011 21:06'!
initialize
rules := OrderedCollection new! !
!TLTextLintChecker methodsFor: 'public' stamp: 'lr 9/9/2011 20:45'!
parse: aString
self parse: aString tokenizer: (TLPlainTokenizer find: aString)! !
!TLTextLintChecker methodsFor: 'public' stamp: 'lr 9/9/2011 20:44'!
parse: aString tokenizer: aTokenizer
document := TLTextPhraser parse: (aTokenizer parse: aString)! !
!TLTextLintChecker methodsFor: 'accessing' stamp: 'lr 9/4/2011 12:45'!
reset
"Reset the results."
results := nil! !
!TLTextLintChecker methodsFor: 'accessing' stamp: 'lr 5/11/2011 21:05'!
results
^ results ifNil: [ results := document allElements gather: [ :each | each checkWith: self ] ]! !
!TLTextLintChecker methodsFor: 'accessing' stamp: 'lr 6/3/2010 16:22'!
rules
^ rules! !
Object subclass: #TLTextLintRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
TLTextLintRule subclass: #TLConnectorRepetitionInParagraphRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLConnectorRepetitionInParagraphRule methodsFor: 'running' stamp: 'JorgeRessia 9/23/2010 23:34'!
checkPhrasesIn: aParagraph addingFailuresTo: results
| counter phrases |
self connectorPhrases
do: [ :eachPhrase |
counter := 0.
phrases := OrderedCollection new.
aParagraph sentences
do: [ :eachSentence |
(eachSentence allPhrasesOfSize: eachPhrase size)
do: [ :each |
each text = eachPhrase text
ifTrue: [
phrases add: each.
counter := counter + 1 ] ] ].
counter > self repetitionLimit
ifTrue: [ results addAll: phrases ] ]! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'running' stamp: 'lr 5/4/2011 20:02'!
checkWordsIn: aParagraph addingFailuresTo: results
| failingWords value wordsCounter |
wordsCounter := Dictionary new.
failingWords := OrderedCollection new.
aParagraph words
do: [ :eachWord |
value := wordsCounter at: eachWord text ifAbsentPut: [ 0 ].
wordsCounter at: eachWord text put: value + 1 ].
wordsCounter
keysAndValuesDo: [ :aKey :aValue |
(aValue > self repetitionLimit and: [ self connectorWords includes: aKey ])
ifTrue: [ failingWords add: aKey ] ].
aParagraph words
do: [ :eachWord |
(failingWords includes: eachWord text)
ifTrue: [ results add: eachWord ] ]! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/23/2010 22:01'!
connectorPhrases
| phrases aPhrase elements |
phrases := OrderedCollection new.
elements := OrderedCollection new.
elements add: (TLWord with: (PPToken on: 'in')).
elements add: (TLWhitespace new).
elements add: (TLWord with: (PPToken on: 'contrast')).
elements add: (TLWhitespace new).
elements add: (TLWord with: (PPToken on: 'to')).
aPhrase := TLPhrase withAll: elements.
phrases add: aPhrase.
elements := OrderedCollection new.
elements add: (TLWord with: (PPToken on: 'in')).
elements add: (TLWhitespace new).
elements add: (TLWord with: (PPToken on: 'addition')).
aPhrase := TLPhrase withAll: elements.
phrases add: aPhrase.
elements := OrderedCollection new.
elements add: (TLWord with: (PPToken on: 'on')).
elements add: (TLWhitespace new).
elements add: (TLWord with: (PPToken on: 'the')).
elements add: (TLWhitespace new).
elements add: (TLWord with: (PPToken on: 'other')).
elements add: (TLWhitespace new).
elements add: (TLWord with: (PPToken on: 'hand')).
aPhrase := TLPhrase withAll: elements.
phrases add: aPhrase.
^ phrases! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/23/2010 21:16'!
connectorWords
^ #('however' 'furthermore' 'still' 'nevertheless')! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/23/2010 21:11'!
name
^ 'Avoid connectors repetition'! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:40'!
rationale
^ 'The constant repetition of the same connectors in a paragraph is weakening.'! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/23/2010 21:56'!
repetitionLimit
^1! !
!TLConnectorRepetitionInParagraphRule methodsFor: 'running' stamp: 'JorgeRessia 9/29/2010 09:55'!
runOnParagraph: aParagraph
| results failures |
results := OrderedCollection new.
self checkWordsIn: aParagraph addingFailuresTo: results.
self checkPhrasesIn: aParagraph addingFailuresTo: results.
failures := OrderedCollection new.
results do: [:each | failures add: (TLRuleFailure on: self at: each) ].
^ failures! !
TLTextLintRule subclass: #TLJoinedSentencesWithCommasRule
instanceVariableNames: 'wordsBeforeCommaExceptions'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLJoinedSentencesWithCommasRule methodsFor: 'initialization' stamp: 'JorgeRessia 5/27/2010 16:55'!
initialize
super initialize.
self initializeWordsBeforeComma! !
!TLJoinedSentencesWithCommasRule methodsFor: 'initialization' stamp: 'lr 5/30/2010 19:27'!
initializeWordsBeforeComma
wordsBeforeCommaExceptions := OrderedCollection new
add: 'or';
add: 'and';
add: 'since';
add: 'however';
add: 'but';
add: 'because';
add: 'though';
add: 'still';
add: 'yet';
add: 'as';
yourself.! !
!TLJoinedSentencesWithCommasRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:54'!
name
^ 'Avoid joined sentences'! !
!TLJoinedSentencesWithCommasRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:40'!
rationale
^ 'Do not join sentences with commas, instead use colons, semi-colons, dashes, or conjunctions.'! !
!TLJoinedSentencesWithCommasRule methodsFor: 'running' stamp: 'JorgeRessia 5/27/2010 17:05'!
runOnSentence: aSentence
| results numberOfCommas children commaIndex wordsBeforeComma wordsAfterComma |
results := OrderedCollection new.
children := aSentence children.
numberOfCommas := children inject: 0 into: [:count :each | (each text = ',') ifTrue: [ count + 1 ] ifFalse: [ count ]].
(numberOfCommas = 1) ifFalse: [^results].
commaIndex := children indexOf: (children detect: [:each | each isPunctuation and: [each text = ',']]).
wordsAfterComma := children select: [:each | each isWord and: [ (children indexOf: each) > commaIndex ]].
(wordsAfterComma size > 0 ) ifFalse: [^results].
(self wordsBeforeComma anySatisfy: [:each | wordsAfterComma first text sameAs: each] ) ifTrue: [^results].
wordsBeforeComma := children select: [:each | each isWord and: [ (children indexOf: each) < commaIndex ]].
((wordsBeforeComma size > 4) and: [wordsAfterComma size > 4]) ifTrue: [ results add: (TLRuleFailure on: self at: aSentence) ].
^results
! !
!TLJoinedSentencesWithCommasRule methodsFor: 'initialization' stamp: 'JorgeRessia 5/27/2010 17:03'!
wordsBeforeComma
^wordsBeforeCommaExceptions ! !
TLTextLintRule subclass: #TLLongParagraphRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLLongParagraphRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/28/2010 11:17'!
maxSentencesPerParagraph
^10! !
!TLLongParagraphRule methodsFor: 'running' stamp: 'lr 9/8/2010 10:54'!
name
^ 'Avoid long paragraph'! !
!TLLongParagraphRule methodsFor: 'accessing' stamp: 'lr 11/30/2010 19:39'!
rationale
^ 'Paragraphs with more than ' , self maxSentencesPerParagraph asString , ' sentences are too long, they should be split into multiple paragraphs.'! !
!TLLongParagraphRule methodsFor: 'running' stamp: 'JorgeRessia 5/28/2010 11:17'!
runOnParagraph: aParagraph
| results |
results := OrderedCollection new.
(aParagraph sentences size > self maxSentencesPerParagraph ) ifTrue: [results add: (TLRuleFailure on: self at: aParagraph)].
^results
! !
TLTextLintRule subclass: #TLLongSentenceRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLLongSentenceRule methodsFor: 'accessing' stamp: 'lr 5/28/2010 11:50'!
maxWordsPerSentence
^ 40! !
!TLLongSentenceRule methodsFor: 'running' stamp: 'lr 9/8/2010 10:54'!
name
^ 'Avoid long sentence'! !
!TLLongSentenceRule methodsFor: 'accessing' stamp: 'lr 11/30/2010 19:39'!
rationale
^ 'Sentences of more than ' , self maxWordsPerSentence asString , ' words are too long, they should be split into multiple sentences.'! !
!TLLongSentenceRule methodsFor: 'running' stamp: 'JorgeRessia 5/28/2010 10:40'!
runOnSentence: aSentence
| results |
results := OrderedCollection new.
(aSentence words size > self maxWordsPerSentence ) ifTrue: [results add: (TLRuleFailure on: self at: aSentence)].
^results
! !
TLTextLintRule subclass: #TLPatternRule
instanceVariableNames: 'pattern'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
TLPatternRule subclass: #TLALotRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLALotRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:38'!
matchingString
^ 'a lot'! !
!TLALotRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:47'!
name
^ 'Avoid "a lot"'! !
!TLALotRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:41'!
rationale
^ 'Avoid using "a lot", it weakens the sentence.'! !
TLPatternRule subclass: #TLARule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLARule methodsFor: 'private' stamp: 'lr 10/31/2010 14:34'!
exceptions
^ #('union' 'united' 'unified' 'unifying' 'us' 'one' 'unit' 'user' 'usage' 'universal' 'unique' 'unit' 'useful' 'uniform')! !
!TLARule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 14:58'!
matchingPattern
^ (self word: 'a') , (self separators) , (self wordIn: self exceptions) not , (self wordTextSatisfying: [ :value | value first isVowel ])! !
!TLARule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:54'!
name
^ 'Avoid "a"'! !
!TLARule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:37'!
rationale
^ 'After "a" only words beginning without a vowel are allowed.'! !
TLPatternRule subclass: #TLAdjectiveSynonymRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLAdjectiveSynonymRule methodsFor: 'accessing' stamp: 'lr 9/6/2011 22:36'!
matchingPattern
| firstWord |
^ (self wordSatisfying: [ :word | (firstWord := word) classifiesAs: #adjective ]) ,
(self separators) ,
(self wordSatisfying: [ :word | (TLThesaurus synonymsOf: firstWord text) includes: word text ])
! !
!TLAdjectiveSynonymRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 16:35'!
name
^ 'Avoid similar adjective synonyms'! !
!TLAdjectiveSynonymRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 16:35'!
rationale
^ 'Avoid using an adjective followed by any word that has a similar meaning.'! !
TLPatternRule subclass: #TLAdverbSynonymRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLAdverbSynonymRule methodsFor: 'accessing' stamp: 'lr 9/6/2011 22:36'!
matchingPattern
| firstWord |
^ (self wordSatisfying: [ :word | (firstWord := word) classifiesAs: #adverb ]) ,
(self separators) ,
(self wordSatisfying: [ :word | (TLThesaurus synonymsOf: firstWord text) includes: word text ])
! !
!TLAdverbSynonymRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 16:36'!
name
^ 'Avoid similar adverb synonyms'! !
!TLAdverbSynonymRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 16:35'!
rationale
^ 'Avoid using an adverb followed by any word that has a similar meaning.'! !
TLPatternRule subclass: #TLAllowToRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLAllowToRule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:03'!
matchingPattern
^ (self word: 'allow') / (self word: 'allows') , (self separators) , (self word: 'to')! !
!TLAllowToRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:53'!
name
^ 'Avoid "allow to"'! !
!TLAllowToRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/4/2010 10:19'!
rationale
^ 'Never use the expressions "allow/s to". This expression requires a direct object.'! !
TLPatternRule subclass: #TLAnRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLAnRule methodsFor: 'private' stamp: 'lr 10/31/2010 14:37'!
exceptions
^ #('honorable' 'honest' 'hour' 'xml' 'hybrid' 'html' 'http')! !
!TLAnRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 14:58'!
matchingPattern
^ (self word: 'an') , (self separators) , (self wordIn: self exceptions) not , (self wordTextSatisfying: [ :value | value first isVowel not ])! !
!TLAnRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:54'!
name
^ 'Avoid "an"'! !
!TLAnRule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:37'!
rationale
^ 'After "an" only words beginning with a vowel are allowed.'! !
TLPatternRule subclass: #TLAsToWhetherRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLAsToWhetherRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:38'!
matchingString
^ 'as to whether'! !
!TLAsToWhetherRule methodsFor: 'accessing' stamp: 'JorgeRessia 10/28/2010 13:10'!
name
^ 'Avoid "as to whether"'! !
!TLAsToWhetherRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:42'!
rationale
^ '"as to whether" is commonly misued, it is enough to write "whether".'! !
TLPatternRule subclass: #TLAvoidMultipleWordsUsageRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLAvoidMultipleWordsUsageRule methodsFor: 'running' stamp: 'JorgeRessia 11/1/2010 15:00'!
matchingPattern
^ self wordIn: self wordsToAvoid! !
!TLAvoidMultipleWordsUsageRule methodsFor: 'running' stamp: 'JorgeRessia 11/1/2010 14:54'!
wordsToAvoid
^ self subclassResponsibility! !
TLAvoidMultipleWordsUsageRule subclass: #TLQualifiersRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLQualifiersRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:09'!
name
^ 'Avoid qualifier'! !
!TLQualifiersRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:43'!
rationale
^ 'Qualifiers are the leeches that infest the pond of prose, sucking the blood of words.'! !
!TLQualifiersRule methodsFor: 'accessing' stamp: 'lr 11/2/2010 07:42'!
wordsToAvoid
^ #('clearly' 'completely' 'exceedingly' 'excellent' 'extremely' 'fairly' 'few' 'huge' 'interestingly' 'largely' 'little' 'many' 'mostly' 'pretty' 'quite' 'rather' 'really' 'relatively' 'remarkably' 'several' 'significantly' 'substantially' 'surprisingly' 'tiny' 'various' 'vast' 'very')! !
TLAvoidMultipleWordsUsageRule subclass: #TLStuffRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLStuffRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:59'!
name
^ 'Avoid "stuff"'! !
!TLStuffRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:43'!
rationale
^ 'Avoid using the word "stuff". Is too general and weakens the sentence.'! !
!TLStuffRule methodsFor: 'running' stamp: 'JorgeRessia 11/1/2010 15:03'!
wordsToAvoid
^ #('stuff' 'stuffs')
! !
TLAvoidMultipleWordsUsageRule subclass: #TLThingRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLThingRule methodsFor: 'running' stamp: 'lr 9/8/2010 11:00'!
name
^ 'Avoid "thing"'! !
!TLThingRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:43'!
rationale
^ 'Avoid using the word "thing". Is too general and weakens the sentence.'! !
!TLThingRule methodsFor: 'running' stamp: 'JorgeRessia 11/1/2010 15:21'!
wordsToAvoid
^ #('thing' 'things')
! !
TLPatternRule subclass: #TLCannotRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLCannotRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:39'!
matchingString
^ 'can not'! !
!TLCannotRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:53'!
name
^'Avoid "can not"'! !
!TLCannotRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/2/2010 19:32'!
rationale
^ '"Can not" as a two word phrase is used for stressing an impossibility, otherwise "cannot" should be used.'! !
TLPatternRule subclass: #TLCaseRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLCaseRule methodsFor: 'accessing' stamp: 'lr 11/30/2010 19:29'!
matchingPattern
^ (self wordIn: #('case' 'cases')) , (self separators) , (self punctuation: '-') optional , (self separators) , (self wordIn: #('grammar' 'grammars' 'harden' 'histories' 'history' 'knife' 'knives' 'law' 'mod' 'sensitive' 'shot' 'stated' 'studies' 'study' 'system')) not! !
!TLCaseRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:01'!
name
^ 'Avoid "case"'! !
!TLCaseRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:43'!
rationale
^ 'Often unnecessarey, e.g. "In many cases, the room lacked air conditioning" can be replaced with "Many of the rooms lacked air conditioning".'! !
TLPatternRule subclass: #TLCertainlyRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLCertainlyRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:44'!
matchingString
^ 'certainly'
! !
!TLCertainlyRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:01'!
name
^ 'Avoid "certainly"'! !
!TLCertainlyRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:43'!
rationale
^ 'Is a manerism that is used indicriminately by some speakers and writers. Avoid its usage if possible.'! !
TLPatternRule subclass: #TLClichesRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLClichesRule methodsFor: 'accessing' stamp: 'lr 5/4/2011 19:49'!
matchingPattern
^ (TLPatternTokenizer parse: 'all things being equal')
/ (TLPatternTokenizer parse: 'all things considered')
/ (TLPatternTokenizer parse: 'as a matter of fact')
/ (TLPatternTokenizer parse: 'as far as I am concerned')
/ (TLPatternTokenizer parse: 'at the end of the day')
/ (TLPatternTokenizer parse: 'at the present time')
/ (TLPatternTokenizer parse: 'due to the fact that')
/ (TLPatternTokenizer parse: 'for all intents and purposes')
/ (TLPatternTokenizer parse: 'for the most part')
/ (TLPatternTokenizer parse: 'for the purpose of')
/ (TLPatternTokenizer parse: 'in a manner of speaking')
/ (TLPatternTokenizer parse: 'in my opinion')
/ (TLPatternTokenizer parse: 'in the event of')
/ (TLPatternTokenizer parse: 'in the final analysis')
/ (TLPatternTokenizer parse: 'it seems that')
/ (TLPatternTokenizer parse: 'the point that I am trying to make')
/ (TLPatternTokenizer parse: 'type of')
/ (TLPatternTokenizer parse: 'what I am trying to say')
/ (TLPatternTokenizer parse: 'what I want to make clear')! !
!TLClichesRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 11:29'!
name
^ 'Avoid cliches'! !
!TLClichesRule methodsFor: 'accessing' stamp: 'lr 9/6/2011 22:26'!
rationale
^ 'Avoid empty phrases (cliches). These phrases mean little. Just cut them off your writing.'! !
TLPatternRule subclass: #TLContinuousWordRepetitionRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLContinuousWordRepetitionRule methodsFor: 'running' stamp: 'JorgeRessia 5/10/2011 14:58'!
matchingPattern
| aWord |
^ (self wordTextSatisfying: [ :value | aWord := value. value isAllDigits not ]) ,
(self wordTextSatisfying: [ :value | aWord sameAs: value]) ! !
!TLContinuousWordRepetitionRule methodsFor: 'running' stamp: 'lr 9/8/2010 11:01'!
name
^ 'Avoid continuous word repetition'! !
!TLContinuousWordRepetitionRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:46'!
rationale
^ 'Continous word repetition is mostly a sign of copy-and-paste text.'! !
TLPatternRule subclass: #TLCouldRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLCouldRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:45'!
matchingString
^ 'could'
! !
!TLCouldRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:01'!
name
^ 'Avoid "could"'! !
!TLCouldRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'Avoid using the word "could" because it weakens the sentence.'! !
TLPatternRule subclass: #TLCurrentlyRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLCurrentlyRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:45'!
matchingString
^ 'currently'
! !
!TLCurrentlyRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:01'!
name
^ 'Avoid "currently"'! !
!TLCurrentlyRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'In the sense of now with a verb in the present tense, "currently" is usually redundant. Emphasis is better achieved through a more precise reference to time.'! !
TLPatternRule subclass: #TLDifferentThanRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLDifferentThanRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:40'!
matchingString
^ 'different than'! !
!TLDifferentThanRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:57'!
name
^ 'Avoid "different than"'! !
!TLDifferentThanRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:46'!
rationale
^ 'Here logic supports stablished usage: one thing differs from another, hence, different from.'! !
TLPatternRule subclass: #TLDoubtButRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLDoubtButRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:40'!
matchingString
^ 'doubt but'! !
!TLDoubtButRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:57'!
name
^ 'Avoid "doubt but"'! !
!TLDoubtButRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:46'!
rationale
^ '"But" is unnecessary after "doubt".'! !
TLPatternRule subclass: #TLEachAndEveryOneRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLEachAndEveryOneRule methodsFor: 'running' stamp: 'lr 11/4/2010 10:40'!
matchingString
^ 'each and every one'! !
!TLEachAndEveryOneRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:58'!
name
^ 'Avoid "each and every one"'! !
!TLEachAndEveryOneRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:46'!
rationale
^ 'Jargon, avoid except in dialog.'! !
TLPatternRule subclass: #TLEnormityRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLEnormityRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:45'!
matchingString
^ 'enormity'
! !
!TLEnormityRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:02'!
name
^ 'Avoid "enormity"'! !
!TLEnormityRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'Use only in the sense of monstrous wickedness. Misleading, if not wrong, when used to express bigness.'! !
TLPatternRule subclass: #TLExcessOfAdjectivesRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLExcessOfAdjectivesRule methodsFor: 'accessing' stamp: 'lr 9/6/2011 22:25'!
matchingPattern
^ (self wordSatisfying: [ :word | word classifiesAs: #adjective ]) ,
(self whitespace) ,
(self wordSatisfying: [ :word | word classifiesAs: #adjective ])
! !
!TLExcessOfAdjectivesRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/30/2011 20:24'!
name
^ 'Avoid excess of adjectives'! !
!TLExcessOfAdjectivesRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/30/2011 20:25'!
rationale
^ 'Avoid using two or more continuous adjectives, be concise and clear.'! !
TLPatternRule subclass: #TLFactorRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLFactorRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:45'!
matchingString
^ 'factor'
! !
!TLFactorRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:07'!
name
^ 'Avoid "factor"'! !
!TLFactorRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'A hackneyed word. The expression can be rephased without it.'! !
TLPatternRule subclass: #TLFunnyRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLFunnyRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:45'!
matchingString
^ 'funny'! !
!TLFunnyRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:08'!
name
^ 'Avoid "funny"'! !
!TLFunnyRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'Avoid it as a means of introduction. Do not announce that something is funny, it should be by itself.'! !
TLPatternRule subclass: #TLHelpButRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLHelpButRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:40'!
matchingString
^ 'help but'! !
!TLHelpButRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:58'!
name
^ 'Avoid "help but"'! !
!TLHelpButRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:47'!
rationale
^ '"But" is unnecessary after "help".'! !
TLPatternRule subclass: #TLHelpToRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLHelpToRule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:07'!
matchingPattern
^ (self word: 'help') / (self word: 'helps') , (self separators) , (self word: 'to')! !
!TLHelpToRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:53'!
name
^'Avoid "help to"'! !
!TLHelpToRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/4/2010 10:41'!
rationale
^ 'Never use the expressions "help/s to". This expression requires a direct object.'! !
TLPatternRule subclass: #TLHoweverRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLHoweverRule methodsFor: 'accessing' stamp: 'lr 11/2/2010 12:27'!
matchingPattern
^ (self anchorBegin) , (self word: 'however')! !
!TLHoweverRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:47'!
name
^ 'Avoid "however"'! !
!TLHoweverRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:47'!
rationale
^ 'Avoid starting a sentence with "however" when the meaning is nevertheless.'! !
TLPatternRule subclass: #TLImportantlyRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLImportantlyRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:46'!
matchingString
^ 'importantly'
! !
!TLImportantlyRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:08'!
name
^ 'Avoid "importantly"'! !
!TLImportantlyRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'Avoid by rephrasing.'! !
TLPatternRule subclass: #TLInOrderToRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLInOrderToRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:41'!
matchingString
^ 'in order to'! !
!TLInOrderToRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:55'!
name
^ 'Avoid "in order to"'! !
!TLInOrderToRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/13/2010 19:55'!
rationale
^ 'This expression is pure clutter and most of the time can be avoided.'! !
TLPatternRule subclass: #TLInRegardsToRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLInRegardsToRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:41'!
matchingString
^ 'in regards to'! !
!TLInRegardsToRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:59'!
name
^ 'Avoid "in regards to"'! !
!TLInRegardsToRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:47'!
rationale
^ 'Often wrongly written "in regards to", should be "in regard to".'! !
TLPatternRule subclass: #TLInTermsOfRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLInTermsOfRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:41'!
matchingString
^ 'in terms of'! !
!TLInTermsOfRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:59'!
name
^ 'Avoid "in terms of"'! !
!TLInTermsOfRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:47'!
rationale
^ 'A piece of padding usually best omitted.'! !
TLPatternRule subclass: #TLInsightfulRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLInsightfulRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:46'!
matchingString
^ 'insightful'
! !
!TLInsightfulRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:08'!
name
^ 'Avoid "insightful"'! !
!TLInsightfulRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:44'!
rationale
^ 'The word is a suspicious overstatement for perceptive. Only used for remarkable visions.'! !
TLPatternRule subclass: #TLInterestingRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLInterestingRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:46'!
matchingString
^ 'interesting'
! !
!TLInterestingRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:09'!
name
^ 'Avoid "interesting"'! !
!TLInterestingRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:45'!
rationale
^ 'Avoid it as a means of introduction. Do not announce that something is interesting.'! !
TLPatternRule subclass: #TLIrregardlessRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLIrregardlessRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:46'!
matchingString
^ 'irregardless'
! !
!TLIrregardlessRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:09'!
name
^ 'Avoid "irregardless"'! !
!TLIrregardlessRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:45'!
rationale
^ 'Should be "regardless". Irregardless is avoided by careful users of English.'! !
TLPatternRule subclass: #TLLetsRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLLetsRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/26/2011 13:45'!
matchingString
^ 'lets'! !
!TLLetsRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/26/2011 13:43'!
name
^ 'Avoid lets'! !
!TLLetsRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/26/2011 13:44'!
rationale
^ 'Let plus a subject should be used instead of using lets.'! !
TLPatternRule subclass: #TLNegativeFormRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLNegativeFormRule methodsFor: 'accessing' stamp: 'lr 5/4/2011 19:53'!
longRationale
^ 'Make definite assertions. Avoid tame, colorless, hesitating, non-committal language.'! !
!TLNegativeFormRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 10:25'!
matchingString
^ 'not'
! !
!TLNegativeFormRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 10:29'!
name
^ 'Avoid negative form'! !
!TLNegativeFormRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 10:29'!
rationale
^ 'When possible, put statements in positive form.'! !
TLPatternRule subclass: #TLNoCommaBeforeThatRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLNoCommaBeforeThatRule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:11'!
matchingPattern
^ (self word) , (self separators) , (self punctuation: ',') , (self separators) , (self word: 'that')! !
!TLNoCommaBeforeThatRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:55'!
name
^ 'Avoid comma'! !
!TLNoCommaBeforeThatRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:47'!
rationale
^ 'In German, you must put a comma before "dass". Not in English.'! !
TLPatternRule subclass: #TLNoContinuousPunctuationMarksRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLNoContinuousPunctuationMarksRule methodsFor: 'running' stamp: 'lr 11/4/2010 10:41'!
matchingPattern
^ (self punctuationIn: self punctuationsToAvoid) , (self punctuationIn: self punctuationsToAvoid)! !
!TLNoContinuousPunctuationMarksRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:00'!
name
^ 'Avoid continuous punctuation'! !
!TLNoContinuousPunctuationMarksRule methodsFor: 'running' stamp: 'JorgeRessia 11/2/2010 08:56'!
punctuationsToAvoid
^ #(',' '.' ':' ';' '!!' '?')
! !
!TLNoContinuousPunctuationMarksRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:47'!
rationale
^ 'There should be no continuous punctuation marks.'! !
TLPatternRule subclass: #TLNoContractionsRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLNoContractionsRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/26/2011 13:32'!
matchingPattern
^ (self word) , (self punctuation: '''') , (self wordIn: #('ve' 't' 'd' 'll' 're' 'm' 's'))! !
!TLNoContractionsRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:55'!
name
^ 'Avoid contraction'! !
!TLNoContractionsRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:48'!
rationale
^ 'Contractions are not allowed since they could be ambiguous.'! !
TLPatternRule subclass: #TLNoSpacesBeforePunctuationMarkRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLNoSpacesBeforePunctuationMarkRule methodsFor: 'running' stamp: 'lr 11/3/2010 14:46'!
matchingPattern
^ (self whitespace) , (self punctuationIn: self punctuationsToAvoid) ! !
!TLNoSpacesBeforePunctuationMarkRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:54'!
name
^ 'Avoid whitespace'! !
!TLNoSpacesBeforePunctuationMarkRule methodsFor: 'running' stamp: 'JorgeRessia 11/2/2010 08:58'!
punctuationsToAvoid
^ #(',' '.' ':' ';' '!!' '?')
! !
!TLNoSpacesBeforePunctuationMarkRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:48'!
rationale
^ 'There should be no whitespaces before any punctuation mark.'! !
TLPatternRule subclass: #TLNounsAndAdjectivesListRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLNounsAndAdjectivesListRule methodsFor: 'accessing' stamp: 'lr 9/6/2011 22:34'!
matchingPattern
| classification |
^ (self wordSatisfying: [ :word |
classification := (word classifiesAs: #adjective)
ifTrue: [ #adjective ]
ifFalse: [
(word classifiesAs: #noun)
ifTrue: [ classification := #noun ]
ifFalse: [ nil ] ].
classification notNil ]) ,
(self separators) ,
(self wordSatisfying: [ :word | word classifiesAs: classification ]) ,
(self separators) ,
(self wordTextSatisfying: [ :value | value = 'and' or: [ value = 'or' ] ]) ,
(self separators) ,
(self wordSatisfying: [ :word | word classifiesAs: classification ])! !
!TLNounsAndAdjectivesListRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/11/2011 21:36'!
name
^ 'Avoid list of terms without comma'! !
!TLNounsAndAdjectivesListRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/11/2011 20:00'!
rationale
^ 'In a serie of three or more terms (adjectives or nouns) with a single conjunction, use a comma after each term except the last.'! !
TLPatternRule subclass: #TLOftenEnoughRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLOftenEnoughRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:42'!
matchingString
^ 'often enough'! !
!TLOftenEnoughRule methodsFor: 'accessing' stamp: 'JorgeRessia 11/2/2010 15:58'!
name
^ 'Avoid "offen enough"'! !
!TLOftenEnoughRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:48'!
rationale
^ 'Avoid using "often enough" it is pure clutter. Use "often" instead.'! !
TLPatternRule subclass: #TLOneOfTheMostRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLOneOfTheMostRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:42'!
matchingString
^ 'one of the most'! !
!TLOneOfTheMostRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:55'!
name
^ 'Avoid "one of the most"'! !
!TLOneOfTheMostRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:48'!
rationale
^ 'Avoid this feeble formula. There is nothing wrong with the grammar the formula is simple threadbare.'! !
TLPatternRule subclass: #TLPassiveVoiceRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLPassiveVoiceRule methodsFor: 'private' stamp: 'lr 11/2/2010 12:46'!
irregularWords
^ #('awoken' 'been' 'born' 'beat' 'become' 'begun' 'bent' 'beset' 'bet' 'bid' 'bidden' 'bound' 'bitten' 'bled' 'blown' 'broken' 'bred' 'brought' 'broadcast' 'built' 'burnt' 'burst' 'bought' 'cast' 'caught' 'chosen' 'clung' 'come' 'cost' 'crept' 'cut' 'dealt' 'dug' 'dived' 'done' 'drawn' 'dreamt' 'driven' 'drunk' 'eaten' 'fallen' 'fed' 'felt' 'fought' 'found' 'fit' 'fled' 'flung' 'flown' 'forbidden' 'forgotten' 'foregone' 'forgiven' 'forsaken' 'frozen' 'gotten' 'given' 'gone' 'ground' 'grown' 'hung' 'heard' 'hidden' 'hit' 'held' 'hurt' 'kept' 'knelt' 'knit' 'known' 'laid' 'led' 'leapt' 'learnt' 'left' 'lent' 'let' 'lain' 'lighted' 'lost' 'made' 'meant' 'met' 'misspelt' 'mistaken' 'mown' 'overcome' 'overdone' 'overtaken' 'overthrown' 'paid' 'pled' 'proven' 'put' 'quit' 'read' 'rid' 'ridden' 'rung' 'risen' 'run' 'sawn' 'said' 'seen' 'sought' 'sold' 'sent' 'set' 'sewn' 'shaken' 'shaven' 'shorn' 'shed' 'shone' 'shod' 'shot' 'shown' 'shrunk' 'shut' 'sung' 'sunk' 'sat' 'slept' 'slain' 'slid' 'slung' 'slit' 'smitten' 'sown' 'spoken' 'sped' 'spent' 'spilt' 'spun' 'spit' 'split' 'spread' 'sprung' 'stood' 'stolen' 'stuck' 'stung' 'stunk' 'stridden' 'struck' 'strung' 'striven' 'sworn' 'swept' 'swollen' 'swum' 'swung' 'taken' 'taught' 'torn' 'told' 'thought' 'thrived' 'thrown' 'thrust' 'trodden' 'understood' 'upheld' 'upset' 'woken' 'worn' 'woven' 'wed' 'wept' 'wound' 'won' 'withheld' 'withstood' 'wrung' 'written')! !
!TLPassiveVoiceRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2011 14:58'!
matchingPattern
"http://matt.might.net/articles/shell-scripts-for-passive-voice-weasel-words-duplicates/"
^ (self wordIn: self verbWords) , (self separators) , ((self wordTextSatisfying: [ :value | value endsWith: 'ed' ]) / (self wordIn: self irregularWords))! !
!TLPassiveVoiceRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:09'!
name
^ 'Avoid passive voice'! !
!TLPassiveVoiceRule methodsFor: 'accessing' stamp: 'lr 9/5/2010 21:58'!
rationale
^ 'Passive voice often hides relevant or explanatory information.'! !
!TLPassiveVoiceRule methodsFor: 'private' stamp: 'lr 11/2/2010 12:45'!
verbWords
^ #('am' 'are' 'were' 'being' 'is' 'been' 'was' 'be')! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 11/2/2010 12:24'!
anchorBegin
^ [ :stream | stream position = 0 ifFalse: [ PPFailure message: 'begin of input expected' at: stream position ] ] asParser! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 11/3/2010 14:45'!
markup
^ PPPredicateObjectParser
on: [ :element | element isMarkup ]
message: 'markup expected'! !
!TLPatternRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:38'!
matchingPattern
"Override in subclasses to answer a custom pattern parser."
^ TLPatternTokenizer parse: self matchingString! !
!TLPatternRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:37'!
matchingString
"Override in subclasses to answer a string pattern."
self error: 'Override #matchingPattern or #matchingString in subclasses to provide pattern.'! !
!TLPatternRule methodsFor: 'private' stamp: 'lr 9/5/2011 19:03'!
newPattern
| result |
result := self matchingPattern.
(result isKindOf: PPFlattenParser)
ifFalse: [ result := result flatten ].
^ result ! !
!TLPatternRule methodsFor: 'accessing' stamp: 'lr 9/5/2011 19:03'!
pattern
"Answer the lazily initialized pattern. Do not override in subclasses."
^ pattern ifNil: [ pattern := self newPattern ]! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 10/31/2010 14:19'!
punctuation
^ PPPredicateObjectParser
on: [ :element | element isPunctuation ]
message: 'punctuation expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 10/31/2010 14:19'!
punctuation: aString
^ PPPredicateObjectParser
on: [ :element | element isPunctuation and: [ element text = aString ] ]
message: 'punctuation expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'JorgeRessia 11/1/2010 10:23'!
punctuationIn: aCollection
^ PPPredicateObjectParser
on: [ :element | element isPunctuation and: [ aCollection anySatisfy: [ :each | element text sameAs: each ] ] ]
message: 'punctuation expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'JorgeRessia 11/1/2010 10:17'!
punctuationSatisfying: aBlock
^ PPPredicateObjectParser
on: [ :element | element isPunctuation and: [ aBlock value: element text ] ]
message: 'punctuation expected'! !
!TLPatternRule methodsFor: 'running' stamp: 'JorgeRessia 11/1/2010 11:23'!
runOnSentence: aSentence
^ (self pattern matchesIn: aSentence children)
collect: [ :each | TLRuleFailure on: self at: (TLPhrase withAll: each) ]! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 11/3/2010 14:45'!
separator
^ self whitespace / self markup! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 10/31/2010 13:58'!
separators
^ self separator star! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 11/3/2010 14:45'!
whitespace
^ PPPredicateObjectParser
on: [ :element | element isWhitespace ]
message: 'whitespace expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 10/31/2010 14:19'!
word
^ PPPredicateObjectParser
on: [ :element | element isWord ]
message: 'word expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 10/31/2010 14:20'!
word: aString
^ PPPredicateObjectParser
on: [ :element | element isWord and: [ element text sameAs: aString ] ]
message: 'word expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'lr 10/31/2010 14:20'!
wordIn: aCollection
^ PPPredicateObjectParser
on: [ :element | element isWord and: [ aCollection anySatisfy: [ :each | element text sameAs: each ] ] ]
message: 'word expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'JorgeRessia 5/10/2011 14:57'!
wordSatisfying: aBlock
^ PPPredicateObjectParser
on: [ :element | element isWord and: [ aBlock value: element ] ]
message: 'word expected'! !
!TLPatternRule methodsFor: 'factory' stamp: 'JorgeRessia 5/10/2011 14:57'!
wordTextSatisfying: aBlock
^ PPPredicateObjectParser
on: [ :element | element isWord and: [ aBlock value: element text ] ]
message: 'word expected'! !
TLPatternRule subclass: #TLRegardedAsBeingRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLRegardedAsBeingRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:42'!
matchingString
^ 'regarded as being'! !
!TLRegardedAsBeingRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:55'!
name
^ 'Avoid "regarded as"'! !
!TLRegardedAsBeingRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:48'!
rationale
^ '"Being" is not appropriate after "regard as".'! !
TLPatternRule subclass: #TLRequireToRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLRequireToRule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:21'!
matchingPattern
^ (self word: 'require') / (self word: 'requires') , (self separators) , (self word: 'to')! !
!TLRequireToRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:56'!
name
^ 'Avoid "required to"'! !
!TLRequireToRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/4/2010 10:25'!
rationale
^ 'Never use the expressions "require/s to". This expression requires a direct object.'! !
TLPatternRule subclass: #TLSoCalledRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLSoCalledRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:42'!
matchingString
^ 'so called'! !
!TLSoCalledRule methodsFor: 'accessing' stamp: 'JorgeRessia 11/2/2010 15:53'!
name
^ 'Avoid "so called"'! !
!TLSoCalledRule methodsFor: 'accessing' stamp: 'JorgeRessia 11/2/2010 15:53'!
rationale
^ 'Avoid using "so called" it is a general expression that adds nothing to the sentence.'! !
TLPatternRule subclass: #TLSoOnRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLSoOnRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:43'!
matchingString
^ 'so on'! !
!TLSoOnRule methodsFor: 'accessing' stamp: 'JorgeRessia 11/2/2010 15:47'!
name
^ 'Avoid "so on"'! !
!TLSoOnRule methodsFor: 'accessing' stamp: 'JorgeRessia 11/2/2010 15:48'!
rationale
^ 'Avoid using "so on" it is a general expression that adds nothing to the sentence.'! !
TLPatternRule subclass: #TLSomehowRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLSomehowRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:46'!
matchingString
^ 'somehow'
! !
!TLSomehowRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:59'!
name
^ 'Avoid "somehow"'! !
!TLSomehowRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:45'!
rationale
^ 'Avoid using the word "somehow". Is too general and weakens the sentence.'! !
TLPatternRule subclass: #TLTheFactIsRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLTheFactIsRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:43'!
matchingString
^ 'the fact is'! !
!TLTheFactIsRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:56'!
name
^ 'Avoid "the fact is"'! !
!TLTheFactIsRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:49'!
rationale
^ 'A bad beginning for a sentence. If you think you are possessed of the truth or fact state it.'! !
TLPatternRule subclass: #TLTheFactThatRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLTheFactThatRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:43'!
matchingString
^ 'the fact that'! !
!TLTheFactThatRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:56'!
name
^ 'Avoid "the fact that"'! !
!TLTheFactThatRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:49'!
rationale
^ '"The fact that" is an especially debilitating expression.'! !
TLPatternRule subclass: #TLTheTruthIsRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLTheTruthIsRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:43'!
matchingString
^ 'the truth is'! !
!TLTheTruthIsRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:56'!
name
^ 'Avoid "the truth is"'! !
!TLTheTruthIsRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:49'!
rationale
^ 'A bad beginning for a sentence. If you think you are possessed of the truth or fact state it.'! !
TLPatternRule subclass: #TLThereIsAreOpenerRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLThereIsAreOpenerRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 11:09'!
matchingPattern
^ (self anchorBegin) , (self word: 'there') , (self separators) , ( (self word: 'is') / (self word: 'are') )! !
!TLThereIsAreOpenerRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 10:59'!
name
^'Avoid "There is/are" openers'! !
!TLThereIsAreOpenerRule methodsFor: 'accessing' stamp: 'JorgeRessia 5/4/2011 11:16'!
rationale
^ 'Avoid the use of There is/are as openers. There are two security guards at the gate -> Two security guards stand at the gate.'! !
TLPatternRule subclass: #TLThusRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLThusRule methodsFor: 'accessing' stamp: 'lr 11/2/2010 12:25'!
matchingPattern
^ (self anchorBegin) , (self word: 'thus')! !
!TLThusRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:09'!
name
^ 'Avoid "thus"'! !
!TLThusRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/2/2010 19:35'!
rationale
^ 'Avoid starting a sentence with "thus". This word should be used for implication between two statements.'! !
TLPatternRule subclass: #TLTrueFactRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLTrueFactRule methodsFor: 'accessing' stamp: 'lr 10/31/2010 14:24'!
matchingPattern
^ (self word: 'true') , (self separators) , ((self word: 'fact') / (self word: 'facts'))! !
!TLTrueFactRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:57'!
name
^ 'Avoid "true fact"'! !
!TLTrueFactRule methodsFor: 'accessing' stamp: 'JorgeRessia 6/10/2010 14:20'!
rationale
^ 'Never use the expressions "true fact/s". It is a tautology.'! !
TLPatternRule subclass: #TLWouldRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLWouldRule methodsFor: 'accessing' stamp: 'lr 11/4/2010 10:46'!
matchingString
^ 'would'
! !
!TLWouldRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:09'!
name
^ 'Avoid "would"'! !
!TLWouldRule methodsFor: 'accessing' stamp: 'JorgeRessia 9/2/2010 19:36'!
rationale
^ 'Avoid using the word "would" because it weakens the sentence.'! !
TLTextLintRule subclass: #TLSerialCommaRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLSerialCommaRule methodsFor: 'private' stamp: 'DamienCassou 9/5/2011 14:37'!
cutAt: aBlock in: aCollection
| result current|
result := OrderedCollection new.
current := OrderedCollection new.
aCollection do: [:e |
e isWhitespace ifFalse: [
(aBlock value: e)
ifTrue: [current isEmpty ifFalse: [result add: current. current:= OrderedCollection new]]
ifFalse: [current add: e]]
].
current isEmpty ifFalse: [result add: current].
^ result! !
!TLSerialCommaRule methodsFor: 'accessing' stamp: 'DamienCassou 9/5/2011 14:15'!
name
^ 'Use the serial comma'! !
!TLSerialCommaRule methodsFor: 'accessing' stamp: 'DamienCassou 9/5/2011 14:15'!
rationale
^ 'Use a comma after the next-to-last item in a series of three or more elements.'! !
!TLSerialCommaRule methodsFor: 'running' stamp: 'lr 9/6/2011 22:56'!
runOnSentence: aSentence
| parts last average match |
parts := self
cutAt: [ :each | each text = ',' ]
in: aSentence children.
parts size < 2
ifTrue: [ ^ #() ].
last := self
cutAt: [ :each | each text = 'and' or: [ each text = 'or' ] ]
in: parts last.
last size < 2
ifTrue: [ ^ #() ].
parts := parts allButLast , last.
parts size < 3
ifTrue: [ ^ #() ].
parts := parts allButFirst.
"only consider it, if all parts have roughly the same number of words"
average := (parts inject: 0 into: [ :count :part | count + part size ]) / parts size asFloat.
(parts allSatisfy: [ :part | part size between: average - 1.5 and: average + 1.5 ])
ifFalse: [ ^ #() ].
^ Array with: (TLRuleFailure on: self at: aSentence)! !
!TLTextLintRule class methodsFor: 'accessing' stamp: 'lr 10/25/2010 19:38'!
allRules
^ self subclasses isEmpty
ifTrue: [ Array with: self new ]
ifFalse: [ self subclasses gather: [ :each | each allRules ] ]! !
!TLTextLintRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 10:44'!
name
^ self subclassResponsibility ! !
!TLTextLintRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/2/2010 17:44'!
rationale
^ self subclassResponsibility! !
!TLTextLintRule methodsFor: 'running' stamp: 'lr 11/2/2010 07:43'!
runOn: aDocument
^ OrderedCollection new
addAll: (self runOnDocument: aDocument);
addAll: (self runOnParagraphsIn: aDocument);
addAll: (self runOnSentencesIn: aDocument);
addAll: (self runOnWordsIn: aDocument);
yourself! !
!TLTextLintRule methodsFor: 'running' stamp: 'lr 11/2/2010 07:43'!
runOnDocument: aDocument
^ #()! !
!TLTextLintRule methodsFor: 'running' stamp: 'lr 11/2/2010 07:43'!
runOnParagraph: aParagraph
^ #()! !
!TLTextLintRule methodsFor: 'running' stamp: 'JorgeRessia 6/3/2010 18:29'!
runOnParagraphsIn: aDocument
^ aDocument paragraphs gather: [ :each | self runOnParagraph: each ]! !
!TLTextLintRule methodsFor: 'running' stamp: 'lr 11/2/2010 07:42'!
runOnSentence: aSentence
^ #()! !
!TLTextLintRule methodsFor: 'running' stamp: 'JorgeRessia 6/3/2010 18:30'!
runOnSentencesIn: aDocument
^ aDocument sentences gather: [ :each | self runOnSentence: each ]! !
!TLTextLintRule methodsFor: 'running' stamp: 'lr 11/2/2010 07:42'!
runOnWord: aWord
^ #()! !
!TLTextLintRule methodsFor: 'running' stamp: 'JorgeRessia 6/3/2010 18:28'!
runOnWordsIn: aDocument
^ aDocument words gather: [ :each | self runOnWord: each ]! !
TLTextLintRule subclass: #TLWordRepetitionInParagraphRule
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLWordRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'lr 9/8/2010 11:00'!
name
^ 'Avoid word repetition'! !
!TLWordRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'lr 11/3/2010 19:49'!
rationale
^ 'The constant repetition of the same words in a paragraph is weakening.'! !
!TLWordRepetitionInParagraphRule methodsFor: 'running' stamp: 'lr 5/4/2011 20:06'!
runOnParagraph: aParagraph
| counts results |
counts := Bag new.
aParagraph words
do: [ :word | counts add: word text ].
results := OrderedCollection new.
aParagraph words do: [ :word |
self wordRepetitionLimit < (counts occurrencesOf: word text)
ifTrue: [ results add: word ] ].
^ results! !
!TLWordRepetitionInParagraphRule methodsFor: 'accessing' stamp: 'JorgeRessia 4/12/2010 10:53'!
wordRepetitionLimit
^2! !
Object subclass: #TLThesaurus
instanceVariableNames: 'groups'
classVariableNames: 'ThesaurusTable defaultDictionary'
poolDictionaries: ''
category: 'TextLint-Model'!
!TLThesaurus class methodsFor: 'private' stamp: 'lr 5/11/2011 19:10'!
createData: aString
"Create the thesarus from http://www.gutenberg.org/ebooks/3202"
"self createData: '/Users/renggli/Downloads/mthesaur.txt'"
| input output zipped |
input := FileStream fileNamed: aString.
input converter: Latin1TextConverter new.
output := self directory
forceNewFileNamed: self filename.
zipped := ZLibWriteStream on: output binary.
[ input atEnd ] whileFalse: [
| words |
words := ((input nextLine findTokens: $,)
reject: [ :each | each anySatisfy: [ :char | char = $ ] ])
collect: [ :each | each asLowercase ].
words isEmpty ifFalse: [
zipped nextInt32Put: words size.
words
do: [ :word | zipped nextPut: word size; nextPutAll: (ByteArray withAll: word) ] ] ].
zipped close.
output close! !
!TLThesaurus class methodsFor: 'accessing' stamp: 'lr 5/11/2011 19:12'!
data
^ ThesaurusTable ifNil: [ ThesaurusTable := self loadData ]! !
!TLThesaurus class methodsFor: 'configuration' stamp: 'lr 5/11/2011 18:57'!
directory
^ FileDirectory default! !
!TLThesaurus class methodsFor: 'private' stamp: 'lr 5/11/2011 18:55'!
downloadData
"Download data from a server."
| response stream |
response := [ HTTPSocket httpGet: self url ]
on: Error
do: [ :err | err messageText ].
response isString
ifTrue: [ ^ self ].
stream := self directory
forceNewFileNamed: self filename.
[ stream binary; nextPutAll: (response binary; contents) ]
ensure: [ stream close ]! !
!TLThesaurus class methodsFor: 'configuration' stamp: 'lr 5/11/2011 18:57'!
filename
^ 'tl-thesaurus.dat'! !
!TLThesaurus class methodsFor: 'initialization' stamp: 'lr 5/11/2011 18:56'!
initialize
Smalltalk addToShutDownList: self! !
!TLThesaurus class methodsFor: 'private' stamp: 'lr 5/12/2011 20:46'!
loadData
"Load data from an external file as fast as possible."
| result stream |
(self directory fileExists: self filename)
ifFalse: [ self downloadData ].
(self directory fileExists: self filename)
ifFalse: [ self error: 'The thesaurus cannot be downloaded from <' , self url , '>.' ].
result := Dictionary new.
stream := self directory
oldFileNamed: self filename.
[ | zstream |
zstream := ZLibReadStream on: stream binary.
[ zstream atEnd ] whileFalse: [
| words count |
words := OrderedCollection new: (count := zstream nextInt32).
count timesRepeat: [ words addLast: (String withAll: (zstream next: zstream next)) ].
result at: words first put: words sorted asArray ] ]
ensure: [ stream close ].
result keysAndValuesDo: [ :key :values |
result at: key put: values sorted ].
^ result! !
!TLThesaurus class methodsFor: 'initialization' stamp: 'lr 5/11/2011 18:56'!
shutDown
ThesaurusTable := nil! !
!TLThesaurus class methodsFor: 'accessing' stamp: 'lr 5/11/2011 19:33'!
synonymsOf: aString
^ self data at: aString asLowercase ifAbsent: [ #() ]! !
!TLThesaurus class methodsFor: 'configuration' stamp: 'lr 5/11/2011 18:57'!
url
^ 'http://www.lukas-renggli.ch/smalltalk/tl-thesaurus.dat'! !
Object subclass: #TLVisitor
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model'!
!TLVisitor methodsFor: 'visiting' stamp: 'DamienCassou 11/21/2011 19:43'!
processDocument: aDocument
self subclassResponsibility ! !
!TLVisitor methodsFor: 'visiting' stamp: 'DamienCassou 11/21/2011 19:43'!
processParagraph: aParagraph
self subclassResponsibility ! !
!TLVisitor methodsFor: 'visiting' stamp: 'DamienCassou 11/21/2011 19:44'!
processPhrase: aPhrase
self subclassResponsibility ! !
!TLVisitor methodsFor: 'visiting' stamp: 'DamienCassou 11/21/2011 19:44'!
processSentence: aSentence
self subclassResponsibility ! !
!TLVisitor methodsFor: 'visiting' stamp: 'DamienCassou 11/21/2011 19:44'!
processSyntacticElement: aSyntacticElement
self subclassResponsibility ! !
Object subclass: #TLWordClassifier
instanceVariableNames: ''
classVariableNames: 'ClassificationTable'
poolDictionaries: ''
category: 'TextLint-Model'!
!TLWordClassifier class methodsFor: 'accessing' stamp: 'lr 9/6/2011 22:10'!
classify: aString
"Answer the possibly classifications of aString."
^ self data at: aString asLowercase ifAbsent: [ #() ]! !
!TLWordClassifier class methodsFor: 'private' stamp: 'lr 5/10/2011 00:17'!
createData: aString
"Create the wordlist. The wordlist we use is from English Wiktionary. The contents of these files is Copyright to the contributors of the English Wiktionary under CC-SA-BY , see for more information. As a source we started from the latest english words available at and processed them with
awk -F '\t' '{ printf ""%s\t%s\n"", tolower($2), tolower($3) }' enwikt-defs-latest-en.tsv | egrep '^[A-Za-z]+.[a-z ]+$' | sed -e 's/proper noun/noun/' -e 's/cardinal number/number/' -e 's/verb form/verb/' -e 's/ordinal number/number/' | grep -v ' ' | sort | uniq | awk -F '\t' '{ printf ""%s\n%s\n"", $1, $2 }' > tl-words.txt"
"self createData: '/Users/renggli/Downloads/tl-words.txt'"
| input output zipped |
input := FileStream fileNamed: aString.
input converter: Latin1TextConverter new.
output := self directory
forceNewFileNamed: self filename.
zipped := ZLibWriteStream on: output binary.
[ input atEnd ] whileFalse: [
| word |
word := input nextLine.
zipped nextPut: word size; nextPutAll: (ByteArray withAll: word) ].
zipped close.
output close! !
!TLWordClassifier class methodsFor: 'accessing' stamp: 'lr 5/9/2011 23:47'!
data
^ ClassificationTable ifNil: [ ClassificationTable := self loadData ]! !
!TLWordClassifier class methodsFor: 'configuration' stamp: 'lr 5/9/2011 23:35'!
directory
^ FileDirectory default! !
!TLWordClassifier class methodsFor: 'accessing' stamp: 'lr 9/6/2011 21:51'!
distributionOfMatches
^ self data inject: Bag new into: [ :bag :types | bag add: types size; yourself ]! !
!TLWordClassifier class methodsFor: 'accessing' stamp: 'lr 9/6/2011 21:51'!
distributionOfTypes
^ self data inject: Bag new into: [ :bag :types | bag addAll: types; yourself ]! !
!TLWordClassifier class methodsFor: 'private' stamp: 'lr 5/9/2011 23:37'!
downloadData
"Download data from a server."
| response stream |
response := [ HTTPSocket httpGet: self url ]
on: Error
do: [ :err | err messageText ].
response isString
ifTrue: [ ^ self ].
stream := self directory
forceNewFileNamed: self filename.
[ stream binary; nextPutAll: (response binary; contents) ]
ensure: [ stream close ]! !
!TLWordClassifier class methodsFor: 'configuration' stamp: 'lr 5/9/2011 23:38'!
filename
^ 'tl-words.dat'! !
!TLWordClassifier class methodsFor: 'initialization' stamp: 'lr 5/9/2011 23:47'!
initialize
Smalltalk addToShutDownList: self! !
!TLWordClassifier class methodsFor: 'private' stamp: 'lr 5/10/2011 00:16'!
loadData
"Load data from an external file as fast as possible."
| result stream |
(self directory fileExists: self filename)
ifFalse: [ self downloadData ].
(self directory fileExists: self filename)
ifFalse: [ self error: 'The word classification cannot be downloaded from <' , self url , '>.' ].
result := Dictionary new.
stream := self directory
oldFileNamed: self filename.
[ | zstream |
zstream := ZLibReadStream on: stream binary.
[ zstream atEnd ] whileFalse: [
(result at: (String withAll: (zstream next: zstream next)) ifAbsentPut: [ Set new ])
add: (String withAll: (zstream next: zstream next)) asSymbol ] ]
ensure: [ stream close ].
result keysAndValuesDo: [ :key :values |
result at: key put: values sorted ].
^ result! !
!TLWordClassifier class methodsFor: 'initialization' stamp: 'lr 5/9/2011 23:43'!
shutDown
ClassificationTable := nil! !
!TLWordClassifier class methodsFor: 'accessing' stamp: 'lr 5/10/2011 00:02'!
types
^ self data inject: Set new into: [ :set :types | set addAll: types; yourself ]! !
!TLWordClassifier class methodsFor: 'configuration' stamp: 'lr 5/9/2011 23:37'!
url
^ 'http://www.lukas-renggli.ch/smalltalk/tl-words.dat'! !
Object subclass: #TLWritingStyle
instanceVariableNames: 'name rules'
classVariableNames: ''
poolDictionaries: ''
category: 'TextLint-Model-Rules'!
!TLWritingStyle class methodsFor: 'instance creation' stamp: 'JorgeRessia 5/10/2010 11:52'!
named: aString formedBy: anArray
^self new initializeNamed: aString formedBy: anArray ! !
!TLWritingStyle class methodsFor: 'accessing' stamp: 'lr 10/25/2010 19:39'!
scientificPaperStyle
| rules |
rules := TLTextLintRule allRules
reject: [ :each | each class = TLWordRepetitionInParagraphRule ].
^ TLWritingStyle named: 'Scientific Paper Style' formedBy: rules! !
!TLWritingStyle methodsFor: 'composing' stamp: 'JorgeRessia 5/12/2010 20:29'!
+ aWritingStyle
^TLWritingStyle
named: (self name, ' + ', aWritingStyle name)
formedBy: (self rules addAll: aWritingStyle rules; yourself)! !
!TLWritingStyle methodsFor: 'composing' stamp: 'JorgeRessia 5/12/2010 20:35'!
- aWritingStyle
^TLWritingStyle
named: (self name, ' - ', aWritingStyle name)
formedBy: (self rules removeAllFoundIn: aWritingStyle rules; yourself)! !
!TLWritingStyle methodsFor: 'testing' stamp: 'JorgeRessia 5/10/2010 11:55'!
includes: aRule
^rules includes: aRule! !
!TLWritingStyle methodsFor: 'initialization' stamp: 'JorgeRessia 5/10/2010 11:58'!
initializeNamed: aString formedBy: aCollection
name := aString.
rules := aCollection asOrderedCollection! !
!TLWritingStyle methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2010 11:54'!
name
^ name! !
!TLWritingStyle methodsFor: 'accessing' stamp: 'JorgeRessia 5/10/2010 11:59'!
rules
^ OrderedCollection withAll: rules! !
TLWordClassifier initialize!
TLWhitespace initialize!
TLThesaurus initialize!