StringPattern.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Tue, 22 Apr 2014 11:29:04 +0200
changeset 3249 16699e7a3c08
parent 3205 154e2d2fcb71
child 3449 21c891242b9d
permissions -rw-r--r--
class: StringPattern added: #data

"{ Package: 'stx:libbasic2' }"

Object subclass:#StringPattern
	instanceVariableNames:'data'
	classVariableNames:''
	poolDictionaries:''
	category:'Collections-Text-Support'
!

StringPattern subclass:#Includes
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:StringPattern
!

StringPattern subclass:#Matches
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:StringPattern
!

Object subclass:#Parser
	instanceVariableNames:'stream errorBlock'
	classVariableNames:''
	poolDictionaries:''
	privateIn:StringPattern
!

StringPattern subclass:#StartsWith
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:StringPattern
!

!StringPattern class methodsFor:'documentation'!

documentation
"
    A StringPattern instances are used to match string. The
    pattern is build from a user-supplied string. It is the
    intention to let the user type the search pattern - it can
    be used for various live searches in lists, dialogs etc.

    This is an unfinished class. More detailed description about
    syntax and algorithm will be added once the results will be
    considered good and the API become stable. 
    If not, blame it on JV :-)

    [author:]
        Jan Vrany <jan.vrany@fit.cvut.cz>

    [instance variables:]

    [class variables:]

    [see also:]

"
! !

!StringPattern class methodsFor:'instance creation'!

includes: aString

    ^Includes new on: aString

    "Created: / 18-10-2011 / 21:22:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

matches: aString

    ^Matches new on: aString

    "Created: / 18-10-2011 / 21:23:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

readFrom:aStringOrStream onError:exceptionBlock

    ^Parser parse: aStringOrStream readStream onError: exceptionBlock

    "
        StringPattern readFrom: 'abcd'
        StringPattern readFrom: ' abcd'
        StringPattern readFrom: ' a??d'
        StringPattern readFrom: ' a*d*'
        StringPattern readFrom: 'abcd*'
    "

    "Created: / 09-08-2011 / 13:39:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

startsWith: aString

    ^StartsWith new on: aString

    "Created: / 09-08-2011 / 13:42:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern methodsFor:'accessing'!

data
    ^ data
! !

!StringPattern methodsFor:'initialization'!

on: anObject

    data := anObject.

    "Created: / 09-08-2011 / 13:42:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern methodsFor:'matching'!

match: string 

    "Answers true if myself match the given string.
     No relaxing done"

    ^self match: string relax: 1.

    "Created: / 09-08-2011 / 13:51:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

match: string relax: relax

    "Answers true if myself match the given string.
     relax argument say how much the matching should
     be relaxed - relax is a number in <1..3>, where
     1 means no relaxing at all (aka exact match). 
     All patterns should support relax == 1. If the relax
     level is not supported by a pattern, false must be 
     returned."

    ^self subclassResponsibility

    "Created: / 09-08-2011 / 13:47:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern methodsFor:'printing & storing'!

printOn:aStream
    "append a printed representation if the receiver to the argument, aStream"

    super printOn:aStream.
    aStream nextPut:$(.
    data printOn: aStream.
    aStream nextPut:$).

    "Modified: / 18-10-2011 / 21:28:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern methodsFor:'utilities'!

matchObject: anObject
    "Return true if pattern matches given object with relax level 1.

    Some heuristics is performed to obtain objects textual
    representation."

    self matchObject: anObject relax: 1

    "Created: / 29-11-2011 / 15:34:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

matchObject: object relax: relax
    "Return true if pattern matches given object..

    Some heuristics is performed to obtain objects textual
    representation."

    object isString ifTrue:[
        ^self match: object relax: relax.
    ].
    object isHierarchicalItem ifTrue:[
        ^self match: object label relax: relax.
    ].

    ^self match: object displayString relax: relax.

    "Created: / 29-11-2011 / 15:37:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern::Includes methodsFor:'matching'!

match:string relax:relax

    relax == 1 ifTrue:[
        ^string includesString: data
    ].
    relax == 2 ifTrue:[
        ^string matches: ('*', data, '*')
    ].
    ^false.

    "Modified: / 11-03-2013 / 14:11:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern::Matches methodsFor:'matching'!

match:string relax:relax

    relax == 1 ifTrue:[
        ^string matches: data
    ].
    relax == 2 ifTrue:[
        | relaxed |
        relaxed := data.
        data first ~~  $* ifTrue:[
            relaxed := '*' , relaxed.
        ].
        data last ~~  $* ifTrue:[
            relaxed := relaxed , '*'.
        ].
        ^string matches: relaxed
    ].
    ^false.

    "Modified: / 18-10-2011 / 21:35:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern::Parser class methodsFor:'parsing'!

parse: aStream onError: errorBlock

    ^self new parse: aStream onError: errorBlock

    "Created: / 09-08-2011 / 13:39:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern::Parser methodsFor:'parsing'!

parse

    "Sorry, no fancy AND/OR patterns now"

   ^self parsePattern.

    "Created: / 09-08-2011 / 13:41:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

parse: aStream onError: aBlock

    stream := aStream.
    errorBlock := aBlock.
    ^self parse.

    "Created: / 09-08-2011 / 13:40:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

parsePattern

    | data |

    stream position == 0 ifTrue:[
        (stream peek notNil and:[stream peek isSeparator]) ifFalse:[
            data := stream upToSeparator.
            (data includes: $*) ifTrue:[
                ^StringPattern matches: data
            ].
            (data includes: $?) ifTrue:[
                ^StringPattern matches: data
            ].
            ^StringPattern startsWith: data    
        ].
    ].

    stream skipSeparators.
    data := stream upToSeparator.
    (data includes: $*) ifTrue:[
        ^StringPattern matches: data
    ].
    (data includes: $?) ifTrue:[
        ^StringPattern matches: data
    ].
    ^StringPattern includes: data

    "Created: / 18-10-2011 / 21:26:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 21-12-2011 / 23:19:06 / jv"
! !

!StringPattern::StartsWith methodsFor:'matching'!

match: string relax: relax

    relax == 1 ifTrue:[
        ^string startsWith: data.
    ].
    relax == 2 ifTrue:[
        ^string includes: data
    ].
    relax == 3 ifTrue:[
        ^string matches: ('*', data, '*')
    ].
    ^false.

    "
        (StringPattern startsWith: 'String') match: 'StringPattern'
        (StringPattern startsWith: 'STring') match: 'StringPattern' relax: 2
    "

    "Created: / 09-08-2011 / 13:50:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!StringPattern class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libbasic2/StringPattern.st,v 1.8 2014-04-22 09:29:04 vrany Exp $'
!

version_CVS
    ^ '$Header: /cvs/stx/stx/libbasic2/StringPattern.st,v 1.8 2014-04-22 09:29:04 vrany Exp $'
! !