Glob.kt

  1. package com.hexagonkt.core.text

  2. import kotlin.IllegalArgumentException
  3. import java.util.regex.PatternSyntaxException

  4. /**
  5.  * [TODO](https://github.com/hexagontk/hexagon/issues/271).
  6.  *
  7.  * @property pattern .
  8.  */
  9. data class Glob(val pattern: String) {

  10.     /** [TODO](https://github.com/hexagontk/hexagon/issues/271). */
  11.     val regex: Regex =
  12.         try {
  13.             globToRegex(pattern).toRegex()
  14.         }
  15.         catch (e: PatternSyntaxException) {
  16.             throw IllegalArgumentException("Pattern: '$pattern' is not a valid Glob", e)
  17.         }

  18.     /**
  19.      * [TODO](https://github.com/hexagontk/hexagon/issues/271).
  20.      *
  21.      * @param text .
  22.      * @return .
  23.      */
  24.     fun matches(text: String): Boolean =
  25.         regex.matches(text)

  26.     private fun globToRegex(pattern: String): String {
  27.         var escaping = false
  28.         var bracesCount = 0

  29.         return pattern.toCharArray().joinToString("") { currentChar ->
  30.             val globPart = when (currentChar) {
  31.                 '.', '(', ')', '+', '|', '^', '$', '@', '%' -> """\$currentChar"""
  32.                 '*' -> if (escaping) """\*""" else ".*"
  33.                 '?' -> if (escaping) """\?""" else "."
  34.                 '\\' -> if (escaping) """\\""" else ""
  35.                 '{' -> if (escaping) """\{""" else "("
  36.                 '}' -> when {
  37.                     bracesCount > 0 && !escaping -> ")"
  38.                     escaping -> """\}"""
  39.                     else -> "}"
  40.                 }
  41.                 ',' -> when {
  42.                     bracesCount > 0 && !escaping -> "|"
  43.                     escaping -> "\\,"
  44.                     else -> ","
  45.                 }
  46.                 else -> currentChar.toString()
  47.             }

  48.             if (currentChar == '{' && !escaping)
  49.                 bracesCount++

  50.             if (currentChar == '}' && !escaping && bracesCount > 0)
  51.                 bracesCount--

  52.             escaping = !escaping && currentChar == '\\'

  53.             globPart
  54.         }
  55.     }
  56. }