Method: PathSpec::GitIgnoreSpec#translate_segment_glob
- Defined in:
- lib/pathspec/gitignorespec.rb
#translate_segment_glob(pattern) ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/pathspec/gitignorespec.rb', line 155 def translate_segment_glob(pattern) # Translates the glob pattern to a regular expression. This is used in # the constructor to translate a path segment glob pattern to its # corresponding regular expression. # # *pattern* (``str``) is the glob pattern. # # Returns the regular expression (``str``). # # NOTE: This is derived from `fnmatch.translate()` and is similar to # the POSIX function `fnmatch()` with the `FNM_PATHNAME` flag set. escape = false regex = '' i = 0 while i < pattern.size # Get next character. char = pattern[i].chr i += 1 # Escape the character. if escape escape = false regex += Regexp.escape(char) # Escape character, escape next character. elsif char == '\\' escape = true # Multi-character wildcard. Match any string (except slashes), # including an empty string. elsif char == '*' regex += '[^/]*' # Single-character wildcard. Match any single character (except # a slash). elsif char == '?' regex += '[^/]' # Braket expression wildcard. Except for the beginning # exclamation mark, the whole braket expression can be used # directly as regex but we have to find where the expression # ends. # - "[][!]" matchs ']', '[' and '!'. # - "[]-]" matchs ']' and '-'. # - "[!]a-]" matchs any character except ']', 'a' and '-'. elsif char == '[' j = i # Pass brack expression negation. j += 1 if j < pattern.size && pattern[j].chr == '!' # Pass first closing braket if it is at the beginning of the # expression. j += 1 if j < pattern.size && pattern[j].chr == ']' # Find closing braket. Stop once we reach the end or find it. j += 1 while j < pattern.size && pattern[j].chr != ']' if j < pattern.size expr = '[' # Braket expression needs to be negated. case pattern[i].chr when '!' expr += '^' i += 1 # POSIX declares that the regex braket expression negation # "[^...]" is undefined in a glob pattern. Python's # `fnmatch.translate()` escapes the caret ('^') as a # literal. To maintain consistency with undefined behavior, # I am escaping the '^' as well. when '^' expr += '\\^' i += 1 end # Escape brackets contained within pattern if pattern[i].chr == ']' && i != j expr += '\]' i += 1 end # Build regex braket expression. Escape slashes so they are # treated as literal slashes by regex as defined by POSIX. expr += pattern[i..j].sub('\\', '\\\\') # Add regex braket expression to regex result. regex += expr # Found end of braket expression. Increment j to be one past # the closing braket: # # [...] # ^ ^ # i j # j += 1 # Set i to one past the closing braket. i = j # Failed to find closing braket, treat opening braket as a # braket literal instead of as an expression. else regex += '\[' end # Regular character, escape it for regex. else regex << Regexp.escape(char) end end regex end |