1 define: #Glob &parents: {Cloneable} &slots: {}.
3 Glob traits define: #Pattern &parents: {Glob} &slots: {
4 #components -> ExtensibleArray new
6 Glob traits define: #PatternMatcher &parents: {Glob} &slots: {#reader. #maskPattern}.
8 Glob traits define: #PatternFailure.
10 Glob traits define: #PatternComponent &parents: {Glob}.
11 Glob traits define: #PatternLiteral &parents: {Glob PatternComponent} &slots: {#string -> ''}.
12 Glob traits define: #PatternRange &parents: {Glob PatternComponent} &slots: {
13 #ranges -> ExtensibleArray new.
16 Glob traits define: #PatternAny &parents: {Glob PatternComponent}.
17 Glob traits define: #PatternAnyOne &parents: {Glob PatternComponent}.
19 glob@(Glob traits) newOn: s
20 [glob Pattern newOn: s].
22 glob@(Glob Pattern traits) newOn: s@(String traits)
24 glob components := glob components new.
25 glob readFrom: s reader.
29 glob@(Glob Pattern traits) readFrom: s@(ReadStream traits)
36 (#{$*. $?. $\[. } includes: token) /\ [prev contents isEmpty not]
37 ifTrue: [matcher nextPut: (glob PatternLiteral new `>> [string := prev contents. ]).
40 $* -> [matcher nextPut: glob PatternAny].
41 $? -> [matcher nextPut: glob PatternAnyOne].
42 $\[ -> [matcher nextPut: (glob readRange := s upTo: $\])]
43 } otherwise: [prev nextPut: token]].
44 prev contents isEmpty ifFalse: [matcher nextPut: (glob PatternLiteral new `>> [string := prev contents. ])]] writingAs: glob components.
47 glob@(Glob Pattern traits) readRange: str@(String traits)
50 p := glob PatternRange new `>>
52 ranges := p ranges new.
53 negate := '^!' includes: (char2 := s peek). ].
56 (char2 := s peek) = $-
57 ifTrue: [s next. p ranges addLast: char -> s next]
58 ifFalse: [p ranges addLast: char]].
62 glob@(Glob Pattern traits) match: str@(String traits) from: pos
64 (glob PatternMatcher new `>> [maskPattern := glob. reader := glob components reader. ]) match: str from: pos
67 glob@(Glob PatternMatcher traits) match: str@(String traits) from: pos
69 "inform: 'match reader: ' ; glob reader printString ; ' pos: ' ; pos printString."
72 (token isSameAs: glob PatternAny)
73 ifTrue: [str size downTo: pos do:
74 [| :start | ((glob new `>> [reader := glob reader clone. ]) match: str from: start) = str size
75 ifTrue: [^ str size]]]
76 ifFalse: [(pos := (token match: str from: pos))
77 == glob PatternFailure ifTrue: [^ pos]]].
81 glob@(Glob Pattern traits) matches: str@(String traits)
83 (match ::= glob match: str from: 0) ~== glob PatternFailure /\ [match = str size]
86 glob@(Glob PatternAny traits) match: str@(String traits) from: pos
88 (pos to: str size - pos)
91 glob@(Glob PatternAnyOne traits) match: str@(String traits) from: pos
93 pos >= str size ifTrue: [glob PatternFailure] ifFalse: [pos + 1]
96 glob@(Glob PatternRange traits) match: str@(String traits) from: pos
98 pos >= str size \/ [glob matches: (str at: pos)] ifTrue: [glob PatternFailure] ifFalse: [pos + 1]
101 glob@(Glob PatternLiteral traits) match: str@(String traits) from: pos
103 pos + glob string size > str size
104 ifTrue: [glob PatternFailure]
105 ifFalse: [(str copyFrom: pos to: pos + glob string size - 1) = glob string
106 ifTrue: [pos + glob string size]
107 ifFalse: [glob PatternFailure]]
110 glob@(Glob PatternRange traits) matches: c@(String Character traits)
113 [| :range | ((range isSameAs: c) /\ [range = c]) \/
114 [c code between: range key code and: c code]]
117 d@(File Locator traits) maskedEntries: mask@(String traits) do: block
119 d maskedEntries: (Glob newOn: mask) do: block
122 l@(File Locator traits) maskedEntries: mask do: block
124 (Directory new `>> [locator := l. ]) maskedEntries: mask do: block
127 l@(File Locator traits) collectMasked: mask
129 [| :result | l maskedEntries: mask do: #(result nextPut: _) `er]
133 d@(File Locator traits) /* mask
134 [d collectMasked: mask].
136 d@(Directory traits) /* mask
137 [d locator collectMasked: mask].
139 d@(Directory traits) maskedEntries: mask do: block
144 [| :each | (mask matches: each) ifTrue:
145 [block applyWith: (File Locator new `>> [readFilenameFrom: each. ])]])].
148 d@(Directory traits) find: block &maxDepth
150 maxDepth `defaultsTo: PositiveInfinity.
151 result ::= Set new writer.
152 d select: block into: result depth: maxDepth.
156 d@(Directory traits) select: block into: result depth: maxDepth
158 maxDepth isZero ifFalse:
159 [entries ::= d entries collect:
160 [| :each | (File RelativeLocator newFrom: d) `>> [readPathElementsFrom: each reader. ]].
161 ((reader ::= entries reader) select: block) >> result.
164 (info := each fileInfo) isNotNil /\ [info isDirectory] /\ [info isLink not]
165 /\ [each name ~= '..'] /\ [each name ~= '.']
166 ifTrue: [(d childNamed: each name) select: block into: result depth: maxDepth - 1]]]