--- a/ListView.st Fri Jan 15 20:43:55 2016 +0100
+++ b/ListView.st Fri Jan 15 22:53:02 2016 +0100
@@ -4707,7 +4707,8 @@
searchBackwardUsingSpec:searchSpec startingAtLine:startLine col:startCol ifFound:block1 ifAbsent:block2
"search for a pattern, if found evaluate block1 with row/col as arguments, if not
found evaluate block2.
- Sorry, but pattern is no regular expression pattern (yet)"
+ Sorry, but pattern is no regular expression pattern (yet).
+ Also, wraps are not done when searching backward."
|lineString
pattern ignCase match fullWord atBeginOfLineOnly
@@ -4756,10 +4757,8 @@
lineString isString ifTrue:[
"/ quick check if pattern is present
col1 := lineString
- findString:pattern
- startingAt:1
- ifAbsent:0
- caseSensitive: ignCase not.
+ findString:pattern startingAt:1
+ ifAbsent:0 caseSensitive: ignCase not.
col1 ~~ 0 ifTrue:[
lineSize := lineString size.
col == -999 ifTrue:[col := lineSize - patternSize + 1].
@@ -4852,20 +4851,23 @@
!
searchForwardUsingSpec:searchSpec startingAtLine:startLine col:startCol ifFound:block1 ifAbsent:block2
- "search for a pattern, if found evaluate block1 with row/col as arguments, if not
- found evaluate block2."
-
- |lineString col pattern match ignCase fullWord atBeginOfLineOnly
- patternSize
+ "search for a pattern, if found evaluate block1 with row/col as arguments,
+ if not found evaluate block2.
+ If the block is a three-arg block, it gets the end-col (or nil, if not found)"
+
+ |lineString col pattern match regexMatch ignCase fullWord atBeginOfLineOnly
+ wrapAtEndOfText patternSize matcher lnr "{Class: SmallInteger}"
line1 "{Class: SmallInteger}"
line2 "{Class: SmallInteger}"
- p realPattern|
+ p realPattern runner foundCol endCol|
pattern := searchSpec pattern.
match := searchSpec match.
+ regexMatch := searchSpec regexMatch.
ignCase := searchSpec ignoreCase.
fullWord := searchSpec fullWord.
atBeginOfLineOnly := searchSpec atBeginOfLineOnly.
+ wrapAtEndOfText := searchSpec wrapAtEndOfText.
patternSize := pattern size.
(list notNil and:[patternSize ~~ 0]) ifTrue:[
@@ -4875,76 +4877,92 @@
line1 := startLine.
line2 := list size.
- (match and:[pattern includesUnescapedMatchCharacters]) ifTrue:[
- "perform a findMatchString (matching)"
- p := pattern species new:0.
- (pattern startsWith:$*) ifFalse:[
- p := p , '*'
- ].
- p := p , pattern.
- (pattern endsWith:$*) ifFalse:[
- p := p , '*'
+ "/ call searchBlock with lnr, col, and line. Cares for wrap
+ runner :=
+ [:searchBlock |
+ |didWrap|
+
+ lnr := line1.
+ didWrap := false.
+ [lnr <= line2] whileTrue:[
+ lineString := list at:lnr.
+ lineString notNil ifTrue:[
+ lineString := lineString asString string.
+ lineString isString ifTrue:[
+ searchBlock value:lnr value:col value:lineString
+ ]
+ ].
+ col := 1.
+ lnr := lnr + 1.
+ lnr > line2 ifTrue:[
+ (wrapAtEndOfText and:[didWrap not]) ifTrue:[
+ didWrap := true.
+ lnr := 1.
+ line2 := line1-1.
+ ].
+ ].
+ ].
+
].
- realPattern := pattern.
- (realPattern startsWith:$*) ifTrue:[
- realPattern := realPattern copyFrom:2
- ].
- line1 to:line2 do:[:lnr |
- lineString := list at:lnr.
- lineString notNil ifTrue:[
- lineString := lineString asString string.
- lineString isString ifTrue:[
- "/ first a crude check ...
+
+ (match and:[regexMatch]) ifTrue:[
+ "perform a findMatchString (regex matching)"
+ matcher := ignCase ifTrue:[pattern asRegexIgnoringCase] ifFalse:[pattern asRegex].
+ runner
+ value:[:lnr :col :lineString |
+ "/ first a crude check ...
+ (matcher hasMatchesIn:lineString) ifTrue:[
+ "/ find which match to show
+ 1 to:matcher subexpressionCount do:[:i |
+ foundCol := matcher subBeginning:i.
+ endCol := matcher subEnd:i.
+ (foundCol notNil and: [endCol notNil]) ifTrue: [
+ foundCol := foundCol + 1. "/ regex uses 0-based indexes (sigh)
+ foundCol >= col ifTrue:[
+ (atBeginOfLineOnly not or:[foundCol == 1]) ifTrue:[
+ ^ block1 value:lnr value:foundCol optionalArgument:endCol.
+ ]]]]]].
+ ] ifFalse:[
+ (match and:[regexMatch or:[pattern includesUnescapedMatchCharacters]]) ifTrue:[
+ "perform a findMatchString (glob matching)"
+ p := pattern species new:0.
+ (pattern startsWith:$*) ifFalse:[p := p , '*'].
+ p := p , pattern.
+ (pattern endsWith:$*) ifFalse:[p := p , '*'].
+ realPattern := pattern.
+ (realPattern startsWith:$*) ifTrue:[
+ realPattern := realPattern copyFrom:2
+ ].
+ runner
+ value:[:lnr :col :lineString |
(p match:lineString caseSensitive:ignCase not) ifTrue:[
"/ ok, there it is; look at which position
- col := lineString
- findMatchString:realPattern
- startingAt:col
- caseSensitive:ignCase not
- ifAbsent:0.
- col ~~ 0 ifTrue:[
- (atBeginOfLineOnly not or:[col == 1]) ifTrue:[
- ^ block1 value:lnr value:col.
+ foundCol := lineString
+ findMatchString:realPattern startingAt:col
+ caseSensitive:ignCase not ifAbsent:0.
+ foundCol ~~ 0 ifTrue:[
+ (atBeginOfLineOnly not or:[foundCol == 1]) ifTrue:[
+ ^ block1 value:lnr value:foundCol optionalArgument:nil.
+ ]]]].
+ ] ifFalse:[
+ "perform a findString (no matching)"
+ p := pattern.
+ runner
+ value:[:lnr :col :lineString |
+ foundCol := lineString
+ findString:p startingAt:col ifAbsent:0 caseSensitive: ignCase not.
+ foundCol ~~ 0 ifTrue:[
+ (fullWord not
+ or:[ (self findBeginOfWordAtLine:lnr col:foundCol) == foundCol
+ and:[ (self findEndOfWordAtLine:lnr col:foundCol) == (foundCol + patternSize - 1) ]]
+ ) ifTrue:[
+ (atBeginOfLineOnly not or:[foundCol == 1]) ifTrue:[
+ ^ block1 value:lnr value:foundCol optionalArgument:nil.
]
]
]
].
- ].
- col := 1
- ]
- ] ifFalse:[
- "perform a findString (no matching)"
- p := pattern "withoutMatchEscapes".
- line1 to:line2 do:[:lnr |
- lineString := list at:lnr.
- lineString notNil ifTrue:[
- lineString := lineString asString string.
- lineString isString ifTrue:[
- col := lineString
- findString:p
- startingAt:col
- ifAbsent:0
- caseSensitive: ignCase not.
- col ~~ 0 ifTrue:[
-"/Transcript showCR:'---'.
-"/Transcript showCR:lineString.
-"/Transcript showCR:col.
-"/Transcript showCR:(self findBeginOfWordAtLine:lnr col:col).
-"/Transcript showCR:(self findEndOfWordAtLine:lnr col:col).
-"/Transcript showCR:(lineString copyFrom:(self findBeginOfWordAtLine:lnr col:col) to:(self findEndOfWordAtLine:lnr col:col)).
- (fullWord not
- or:[ (self findBeginOfWordAtLine:lnr col:col) == col
- and:[ (self findEndOfWordAtLine:lnr col:col) == (col + patternSize - 1) ]]
- ) ifTrue:[
- (atBeginOfLineOnly not or:[col == 1]) ifTrue:[
- ^ block1 value:lnr value:col.
- ]
- ]
- ]
- ]
- ].
- col := 1
- ]
+ ].
].
]
].