src/Pure/General/path.scala
changeset 75393 87ebf5a50283
parent 75312 e641ac92b489
child 75696 c79df6dc2803
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
    13 import java.nio.file.{Path => JPath}
    13 import java.nio.file.{Path => JPath}
    14 
    14 
    15 import scala.util.matching.Regex
    15 import scala.util.matching.Regex
    16 
    16 
    17 
    17 
    18 object Path
    18 object Path {
    19 {
       
    20   /* path elements */
    19   /* path elements */
    21 
    20 
    22   sealed abstract class Elem
    21   sealed abstract class Elem
    23   private case class Root(name: String) extends Elem
    22   private case class Root(name: String) extends Elem
    24   private case class Basic(name: String) extends Elem
    23   private case class Basic(name: String) extends Elem
    93   val ISABELLE_HOME: Path = variable("ISABELLE_HOME")
    92   val ISABELLE_HOME: Path = variable("ISABELLE_HOME")
    94 
    93 
    95 
    94 
    96   /* explode */
    95   /* explode */
    97 
    96 
    98   def explode(str: String): Path =
    97   def explode(str: String): Path = {
    99   {
       
   100     def explode_elem(s: String): Elem =
    98     def explode_elem(s: String): Elem =
   101       try {
    99       try {
   102         if (s == "..") Parent
   100         if (s == "..") Parent
   103         else if (s == "~") Variable("USER_HOME")
   101         else if (s == "~") Variable("USER_HOME")
   104         else if (s == "~~") Variable("ISABELLE_HOME")
   102         else if (s == "~~") Variable("ISABELLE_HOME")
   146     Long_Name.explode(name).exists(a => reserved_windows.contains(Word.uppercase(a)))
   144     Long_Name.explode(name).exists(a => reserved_windows.contains(Word.uppercase(a)))
   147 
   145 
   148 
   146 
   149   /* case-insensitive names */
   147   /* case-insensitive names */
   150 
   148 
   151   def check_case_insensitive(paths: List[Path]): Unit =
   149   def check_case_insensitive(paths: List[Path]): Unit = {
   152   {
       
   153     val table =
   150     val table =
   154       paths.foldLeft(Multi_Map.empty[String, String]) { case (tab, path) =>
   151       paths.foldLeft(Multi_Map.empty[String, String]) { case (tab, path) =>
   155         val name = path.expand.implode
   152         val name = path.expand.implode
   156         tab.insert(Word.lowercase(name), name)
   153         tab.insert(Word.lowercase(name), name)
   157       }
   154       }
   162     }
   159     }
   163   }
   160   }
   164 }
   161 }
   165 
   162 
   166 
   163 
   167 final class Path private(protected val elems: List[Path.Elem]) // reversed elements
   164 final class Path private(
   168 {
   165   protected val elems: List[Path.Elem]  // reversed elements
       
   166 ) {
   169   override def hashCode: Int = elems.hashCode
   167   override def hashCode: Int = elems.hashCode
   170   override def equals(that: Any): Boolean =
   168   override def equals(that: Any): Boolean =
   171     that match {
   169     that match {
   172       case other: Path => elems == other.elems
   170       case other: Path => elems == other.elems
   173       case _ => false
   171       case _ => false
   235   def log: Path = ext("log")
   233   def log: Path = ext("log")
   236   def orig: Path = ext("orig")
   234   def orig: Path = ext("orig")
   237   def patch: Path = ext("patch")
   235   def patch: Path = ext("patch")
   238   def shasum: Path = ext("shasum")
   236   def shasum: Path = ext("shasum")
   239 
   237 
   240   def backup: Path =
   238   def backup: Path = {
   241   {
       
   242     val (prfx, s) = split_path
   239     val (prfx, s) = split_path
   243     prfx + Path.basic(s + "~")
   240     prfx + Path.basic(s + "~")
   244   }
   241   }
   245 
   242 
   246   def backup2: Path =
   243   def backup2: Path = {
   247   {
       
   248     val (prfx, s) = split_path
   244     val (prfx, s) = split_path
   249     prfx + Path.basic(s + "~~")
   245     prfx + Path.basic(s + "~~")
   250   }
   246   }
   251 
   247 
   252   def exe: Path = ext("exe")
   248   def exe: Path = ext("exe")
   253   def platform_exe: Path = if (Platform.is_windows) exe else this
   249   def platform_exe: Path = if (Platform.is_windows) exe else this
   254 
   250 
   255   private val Ext = new Regex("(.*)\\.([^.]*)")
   251   private val Ext = new Regex("(.*)\\.([^.]*)")
   256 
   252 
   257   def split_ext: (Path, String) =
   253   def split_ext: (Path, String) = {
   258   {
       
   259     val (prefix, base) = split_path
   254     val (prefix, base) = split_path
   260     base match {
   255     base match {
   261       case Ext(b, e) => (prefix + Path.basic(b), e)
   256       case Ext(b, e) => (prefix + Path.basic(b), e)
   262       case _ => (prefix + Path.basic(base), "")
   257       case _ => (prefix + Path.basic(base), "")
   263     }
   258     }
   269   def squash: Path = new Path(elems.map(elem => Path.Basic(Path.squash_elem(elem))))
   264   def squash: Path = new Path(elems.map(elem => Path.Basic(Path.squash_elem(elem))))
   270 
   265 
   271 
   266 
   272   /* expand */
   267   /* expand */
   273 
   268 
   274   def expand_env(env: JMap[String, String]): Path =
   269   def expand_env(env: JMap[String, String]): Path = {
   275   {
       
   276     def eval(elem: Path.Elem): List[Path.Elem] =
   270     def eval(elem: Path.Elem): List[Path.Elem] =
   277       elem match {
   271       elem match {
   278         case Path.Variable(s) =>
   272         case Path.Variable(s) =>
   279           val path = Path.explode(Isabelle_System.getenv_strict(s, env))
   273           val path = Path.explode(Isabelle_System.getenv_strict(s, env))
   280           if (path.elems.exists(_.isInstanceOf[Path.Variable]))
   274           if (path.elems.exists(_.isInstanceOf[Path.Variable]))
   291   def file_name: String = expand.base.implode
   285   def file_name: String = expand.base.implode
   292 
   286 
   293 
   287 
   294   /* implode wrt. given directories */
   288   /* implode wrt. given directories */
   295 
   289 
   296   def implode_symbolic: String =
   290   def implode_symbolic: String = {
   297   {
       
   298     val directories =
   291     val directories =
   299       Library.space_explode(':', Isabelle_System.getenv("ISABELLE_DIRECTORIES")).reverse
   292       Library.space_explode(':', Isabelle_System.getenv("ISABELLE_DIRECTORIES")).reverse
   300     val full_name = expand.implode
   293     val full_name = expand.implode
   301     directories.view.flatMap(a =>
   294     directories.view.flatMap(a =>
   302       try {
   295       try {