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 ifTrue: [^ glob PatternFailure].
104 (str copyFrom: pos to: pos + glob string size - 1) = glob string ifTrue: [pos + glob string size] ifFalse: [glob PatternFailure]
107 glob@(Glob PatternRange traits) matches: c@(String Character traits)
110 [| :range | ((range isSameAs: c) /\ [range = c]) \/
111 [c code between: range key code and: c code]]
114 d@(File Locator traits) maskedEntries: mask@(String traits) do: block
116 d maskedEntries: (Glob newOn: mask) do: block
119 l maskedEntries: mask@(Regex Regex traits) do: block
121 l maskedEntries: (Regex Matcher newOn: mask) do: block
124 l@(File Locator traits) maskedEntries: mask do: block
126 (Directory new `>> [locator := l. ]) maskedEntries: mask do: block
129 l@(File Locator traits) collectMasked: mask
131 [| :result | l maskedEntries: mask do: #(result nextPut: _) `er]
135 d@(File Locator traits) /* mask
136 [d collectMasked: mask].
138 d@(Directory traits) /* mask
139 [d locator collectMasked: mask].
141 d@(Directory traits) maskedEntries: mask do: block
146 [| :each | (mask matches: each) ifTrue:
147 [block applyWith: (File Locator new `>> [readFilenameFrom: each. ])]])].
150 d@(Directory traits) find: block &maxDepth: maxDepth
152 maxDepth `defaultsTo: PositiveInfinity.
153 result ::= Set new writer.
154 d select: block into: result depth: maxDepth.
158 d@(Directory traits) select: block into: result depth: maxDepth
160 maxDepth isZero ifFalse:
161 [entries ::= d entries collect:
162 [| :each | (File RelativeLocator newFrom: d) `>> [readPathElementsFrom: each reader. ]].
163 ((reader ::= entries reader) select: block) >> result.
166 (info := each fileInfo) isNotNil /\ [info isDirectory] /\ [info isLink not]
167 /\ [each name ~= '..'] /\ [each name ~= '.']
168 ifTrue: [(d childNamed: each name) select: block into: result depth: maxDepth - 1]]]